* src/pic/device.c,
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
29                 Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #include "common.h"
40 #include "SDCCpeeph.h"
41 #include "ralloc.h"
42 #include "pcode.h"
43 #include "gen.h"
44
45
46 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
47 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
48 void genMult8X8_8 (operand *, operand *,operand *);
49 pCode *AssembleLine(char *line);
50 extern void printpBlock(FILE *of, pBlock *pb);
51
52 static int labelOffset=0;
53 extern int debug_verbose;
54 static int optimized_for_speed = 0;
55
56 /* max_key keeps track of the largest label number used in 
57    a function. This is then used to adjust the label offset
58    for the next function.
59 */
60 static int max_key=0;
61 static int GpsuedoStkPtr=0;
62
63 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
64 unsigned int pic14aopLiteral (value *val, int offset);
65 const char *AopType(short type);
66 static iCode *ifxForOp ( operand *op, iCode *ic );
67
68 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
69
70 /* this is the down and dirty file with all kinds of 
71    kludgy & hacky stuff. This is what it is all about
72    CODE GENERATION for a specific MCU . some of the
73    routines may be reusable, will have to see */
74
75 static char *zero = "#0x00";
76 static char *one  = "#0x01";
77 static char *spname = "sp";
78
79 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
80 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
81 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
82 static char **fReturn = fReturnpic14;
83
84 static char *accUse[] = {"a","b"};
85
86 //static short rbank = -1;
87
88 static struct {
89     short r0Pushed;
90     short r1Pushed;
91     short accInUse;
92     short inLine;
93     short debugLine;
94     short nRegsSaved;
95     set *sendSet;
96 } _G;
97
98 /* Resolved ifx structure. This structure stores information
99    about an iCode ifx that makes it easier to generate code.
100 */
101 typedef struct resolvedIfx {
102   symbol *lbl;     /* pointer to a label */
103   int condition;   /* true or false ifx */
104   int generated;   /* set true when the code associated with the ifx
105                     * is generated */
106 } resolvedIfx;
107
108 extern int pic14_ptrRegReq ;
109 extern int pic14_nRegs;
110 extern FILE *codeOutFile;
111 static void saverbank (int, iCode *,bool);
112
113 static lineNode *lineHead = NULL;
114 static lineNode *lineCurr = NULL;
115
116 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
117 0xE0, 0xC0, 0x80, 0x00};
118 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
119 0x07, 0x03, 0x01, 0x00};
120
121 static  pBlock *pb;
122
123 /*-----------------------------------------------------------------*/
124 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
125 /*                 exponent of 2 is returned, otherwise -1 is      */
126 /*                 returned.                                       */
127 /* note that this is similar to the function `powof2' in SDCCsymt  */
128 /* if(n == 2^y)                                                    */
129 /*   return y;                                                     */
130 /* return -1;                                                      */
131 /*-----------------------------------------------------------------*/
132 static int my_powof2 (unsigned long num)
133 {
134   if(num) {
135     if( (num & (num-1)) == 0) {
136       int nshifts = -1;
137       while(num) {
138         num>>=1;
139         nshifts++;
140       }
141       return nshifts;
142     }
143   }
144
145   return -1;
146 }
147
148 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
149 {
150
151   DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
152                        line_no,
153                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
154                        ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
155                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
156                        ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
157                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
158                        ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
159                        ((result) ? AOP_SIZE(result) : 0));
160
161 }
162
163 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
164 {
165
166   DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
167                        line_no,
168                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
169                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
170                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
171                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
172                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
173                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
174
175 }
176
177 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
178 {
179     va_list ap;
180     char lb[INITIAL_INLINEASM];  
181     char *lbp = lb;
182
183     if(!debug_verbose)
184       return;
185
186     va_start(ap,fmt);   
187
188     if (inst && *inst) {
189         if (fmt && *fmt)
190             sprintf(lb,"%s\t",inst);
191         else
192             sprintf(lb,"%s",inst);
193         vsprintf(lb+(strlen(lb)),fmt,ap);
194     }  else
195         vsprintf(lb,fmt,ap);
196
197     while (isspace(*lbp)) lbp++;
198
199     if (lbp && *lbp) 
200         lineCurr = (lineCurr ?
201                     connectLine(lineCurr,newLineNode(lb)) :
202                     (lineHead = newLineNode(lb)));
203     lineCurr->isInline = _G.inLine;
204     lineCurr->isDebug  = _G.debugLine;
205
206     addpCode2pBlock(pb,newpCodeCharP(lb));
207
208     va_end(ap);
209 }
210
211
212 void emitpLabel(int key)
213 {
214   addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
215 }
216
217 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
218 {
219   if(pcop)
220     addpCode2pBlock(pb,newpCode(poc,pcop));
221   else
222     DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
223 }
224
225 void emitpcodeNULLop(PIC_OPCODE poc)
226 {
227
228   addpCode2pBlock(pb,newpCode(poc,NULL));
229
230 }
231
232
233 /*-----------------------------------------------------------------*/
234 /* pic14_emitcode - writes the code into a file : for now it is simple    */
235 /*-----------------------------------------------------------------*/
236 void pic14_emitcode (char *inst,char *fmt, ...)
237 {
238     va_list ap;
239     char lb[INITIAL_INLINEASM];  
240     char *lbp = lb;
241
242     va_start(ap,fmt);   
243
244     if (inst && *inst) {
245         if (fmt && *fmt)
246             sprintf(lb,"%s\t",inst);
247         else
248             sprintf(lb,"%s",inst);
249         vsprintf(lb+(strlen(lb)),fmt,ap);
250     }  else
251         vsprintf(lb,fmt,ap);
252
253     while (isspace(*lbp)) lbp++;
254
255     if (lbp && *lbp) 
256         lineCurr = (lineCurr ?
257                     connectLine(lineCurr,newLineNode(lb)) :
258                     (lineHead = newLineNode(lb)));
259     lineCurr->isInline = _G.inLine;
260     lineCurr->isDebug  = _G.debugLine;
261
262     if(debug_verbose)
263       addpCode2pBlock(pb,newpCodeCharP(lb));
264
265     va_end(ap);
266 }
267
268
269 /*-----------------------------------------------------------------*/
270 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
271 /*-----------------------------------------------------------------*/
272 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
273 {
274     bool r0iu = FALSE , r1iu = FALSE;
275     bool r0ou = FALSE , r1ou = FALSE;
276
277     /* the logic: if r0 & r1 used in the instruction
278     then we are in trouble otherwise */
279
280     /* first check if r0 & r1 are used by this
281     instruction, in which case we are in trouble */
282     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
283         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
284     {
285         goto endOfWorld;      
286     }
287
288     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
289     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
290
291     /* if no usage of r0 then return it */
292     if (!r0iu && !r0ou) {
293         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
294         (*aopp)->type = AOP_R0;
295         
296         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
297     }
298
299     /* if no usage of r1 then return it */
300     if (!r1iu && !r1ou) {
301         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
302         (*aopp)->type = AOP_R1;
303
304         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
305     }    
306
307     /* now we know they both have usage */
308     /* if r0 not used in this instruction */
309     if (!r0iu) {
310         /* push it if not already pushed */
311         if (!_G.r0Pushed) {
312           //pic14_emitcode ("push","%s",
313           //          pic14_regWithIdx(R0_IDX)->dname);
314             _G.r0Pushed++ ;
315         }
316         
317         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
318         (*aopp)->type = AOP_R0;
319
320         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
321     }
322
323     /* if r1 not used then */
324
325     if (!r1iu) {
326         /* push it if not already pushed */
327         if (!_G.r1Pushed) {
328           //pic14_emitcode ("push","%s",
329           //          pic14_regWithIdx(R1_IDX)->dname);
330             _G.r1Pushed++ ;
331         }
332         
333         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
334         (*aopp)->type = AOP_R1;
335         return pic14_regWithIdx(R1_IDX);
336     }
337
338 endOfWorld :
339     /* I said end of world but not quite end of world yet */
340     /* if this is a result then we can push it on the stack*/
341     if (result) {
342         (*aopp)->type = AOP_STK;    
343         return NULL;
344     }
345
346     /* other wise this is true end of the world */
347     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
348            "getFreePtr should never reach here");
349     exit(0);
350 }
351
352 /*-----------------------------------------------------------------*/
353 /* newAsmop - creates a new asmOp                                  */
354 /*-----------------------------------------------------------------*/
355 asmop *newAsmop (short type)
356 {
357     asmop *aop;
358
359     aop = Safe_calloc(1,sizeof(asmop));
360     aop->type = type;
361     return aop;
362 }
363
364 static void genSetDPTR(int n)
365 {
366     if (!n)
367     {
368         pic14_emitcode(";", "Select standard DPTR");
369         pic14_emitcode("mov", "dps, #0x00");
370     }
371     else
372     {
373         pic14_emitcode(";", "Select alternate DPTR");
374         pic14_emitcode("mov", "dps, #0x01");
375     }
376 }
377
378 /*-----------------------------------------------------------------*/
379 /* resolveIfx - converts an iCode ifx into a form more useful for  */
380 /*              generating code                                    */
381 /*-----------------------------------------------------------------*/
382 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
383 {
384   if(!resIfx) 
385     return;
386
387   //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
388
389   resIfx->condition = 1;    /* assume that the ifx is true */
390   resIfx->generated = 0;    /* indicate that the ifx has not been used */
391
392   if(!ifx) {
393     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
394 /*
395     DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
396                         __FUNCTION__,__LINE__,resIfx->lbl->key);
397 */
398   } else {
399     if(IC_TRUE(ifx)) {
400       resIfx->lbl = IC_TRUE(ifx);
401     } else {
402       resIfx->lbl = IC_FALSE(ifx);
403       resIfx->condition = 0;
404     }
405 /*
406     if(IC_TRUE(ifx)) 
407       DEBUGpic14_emitcode("; ***","ifx true is non-null");
408     if(IC_FALSE(ifx)) 
409       DEBUGpic14_emitcode("; ***","ifx false is non-null");
410 */
411   }
412
413   //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
414
415 }
416 /*-----------------------------------------------------------------*/
417 /* pointerCode - returns the code for a pointer type               */
418 /*-----------------------------------------------------------------*/
419 static int pointerCode (sym_link *etype)
420 {
421
422     return PTR_TYPE(SPEC_OCLS(etype));
423
424 }
425
426 /*-----------------------------------------------------------------*/
427 /* aopForSym - for a true symbol                                   */
428 /*-----------------------------------------------------------------*/
429 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
430 {
431     asmop *aop;
432     memmap *space= SPEC_OCLS(sym->etype);
433
434     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
435     /* if already has one */
436     if (sym->aop)
437         return sym->aop;
438
439     /* assign depending on the storage class */
440     /* if it is on the stack or indirectly addressable */
441     /* space we need to assign either r0 or r1 to it   */    
442     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
443         sym->aop = aop = newAsmop(0);
444         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
445         aop->size = getSize(sym->type);
446
447         /* now assign the address of the variable to 
448         the pointer register */
449         if (aop->type != AOP_STK) {
450
451             if (sym->onStack) {
452                     if ( _G.accInUse )
453                         pic14_emitcode("push","acc");
454
455                     pic14_emitcode("mov","a,_bp");
456                     pic14_emitcode("add","a,#0x%02x",
457                              ((sym->stack < 0) ?
458                               ((char)(sym->stack - _G.nRegsSaved )) :
459                               ((char)sym->stack)) & 0xff);
460                     pic14_emitcode("mov","%s,a",
461                              aop->aopu.aop_ptr->name);
462
463                     if ( _G.accInUse )
464                         pic14_emitcode("pop","acc");
465             } else
466                 pic14_emitcode("mov","%s,#%s",
467                          aop->aopu.aop_ptr->name,
468                          sym->rname);
469             aop->paged = space->paged;
470         } else
471             aop->aopu.aop_stk = sym->stack;
472         return aop;
473     }
474     
475     if (sym->onStack && options.stack10bit)
476     {
477         /* It's on the 10 bit stack, which is located in
478          * far data space.
479          */
480          
481       //DEBUGpic14_emitcode(";","%d",__LINE__);
482
483         if ( _G.accInUse )
484                 pic14_emitcode("push","acc");
485
486         pic14_emitcode("mov","a,_bp");
487         pic14_emitcode("add","a,#0x%02x",
488                  ((sym->stack < 0) ?
489                    ((char)(sym->stack - _G.nRegsSaved )) :
490                    ((char)sym->stack)) & 0xff);
491         
492         genSetDPTR(1);
493         pic14_emitcode ("mov","dpx1,#0x40");
494         pic14_emitcode ("mov","dph1,#0x00");
495         pic14_emitcode ("mov","dpl1, a");
496         genSetDPTR(0);
497         
498         if ( _G.accInUse )
499             pic14_emitcode("pop","acc");
500             
501         sym->aop = aop = newAsmop(AOP_DPTR2);
502         aop->size = getSize(sym->type); 
503         return aop;
504     }
505
506     //DEBUGpic14_emitcode(";","%d",__LINE__);
507     /* if in bit space */
508     if (IN_BITSPACE(space)) {
509         sym->aop = aop = newAsmop (AOP_CRY);
510         aop->aopu.aop_dir = sym->rname ;
511         aop->size = getSize(sym->type);
512         //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
513         return aop;
514     }
515     /* if it is in direct space */
516     if (IN_DIRSPACE(space)) {
517         sym->aop = aop = newAsmop (AOP_DIR);
518         aop->aopu.aop_dir = sym->rname ;
519         aop->size = getSize(sym->type);
520         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
521         return aop;
522     }
523
524     /* special case for a function */
525     if (IS_FUNC(sym->type)) {   
526
527       sym->aop = aop = newAsmop(AOP_PCODE);
528       aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
529       PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
530       PCOI(aop->aopu.pcop)->_function = 1;
531       PCOI(aop->aopu.pcop)->index = 0;
532       aop->size = FPTRSIZE; 
533       /*
534         sym->aop = aop = newAsmop(AOP_IMMD);    
535         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
536         strcpy(aop->aopu.aop_immd,sym->rname);
537         aop->size = FPTRSIZE; 
538       */
539         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
540         return aop;
541     }
542
543
544     /* only remaining is far space */
545     /* in which case DPTR gets the address */
546     sym->aop = aop = newAsmop(AOP_PCODE);
547
548     aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
549     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
550     PCOI(aop->aopu.pcop)->index = 0;
551
552     DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
553                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
554
555     allocDirReg (IC_LEFT(ic));
556
557     aop->size = FPTRSIZE; 
558 /*
559     DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
560     sym->aop = aop = newAsmop(AOP_DPTR);
561     pic14_emitcode ("mov","dptr,#%s", sym->rname);
562     aop->size = getSize(sym->type);
563
564     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
565 */
566
567     /* if it is in code space */
568     if (IN_CODESPACE(space))
569         aop->code = 1;
570
571     return aop;     
572 }
573
574 /*-----------------------------------------------------------------*/
575 /* aopForRemat - rematerialzes an object                           */
576 /*-----------------------------------------------------------------*/
577 static asmop *aopForRemat (operand *op) // x symbol *sym)
578 {
579   symbol *sym = OP_SYMBOL(op);
580   iCode *ic = NULL;
581   asmop *aop = newAsmop(AOP_PCODE);
582   int val = 0;
583   int offset = 0;
584
585   ic = sym->rematiCode;
586
587   DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
588   if(IS_OP_POINTER(op)) {
589     DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
590   }
591   for (;;) {
592     if (ic->op == '+') {
593       val += (int) operandLitValue(IC_RIGHT(ic));
594     } else if (ic->op == '-') {
595       val -= (int) operandLitValue(IC_RIGHT(ic));
596     } else
597       break;
598         
599     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
600   }
601
602   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
603   aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
604   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
605   PCOI(aop->aopu.pcop)->index = val;
606
607   DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
608                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
609                       val, IS_PTR_CONST(operandType(op)));
610
611   //    DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
612
613   allocDirReg (IC_LEFT(ic));
614
615   return aop;        
616 }
617
618 int aopIdx (asmop *aop, int offset)
619 {
620   if(!aop)
621     return -1;
622
623   if(aop->type !=  AOP_REG)
624     return -2;
625         
626   return aop->aopu.aop_reg[offset]->rIdx;
627
628 }
629 /*-----------------------------------------------------------------*/
630 /* regsInCommon - two operands have some registers in common       */
631 /*-----------------------------------------------------------------*/
632 static bool regsInCommon (operand *op1, operand *op2)
633 {
634     symbol *sym1, *sym2;
635     int i;
636
637     /* if they have registers in common */
638     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
639         return FALSE ;
640
641     sym1 = OP_SYMBOL(op1);
642     sym2 = OP_SYMBOL(op2);
643
644     if (sym1->nRegs == 0 || sym2->nRegs == 0)
645         return FALSE ;
646
647     for (i = 0 ; i < sym1->nRegs ; i++) {
648         int j;
649         if (!sym1->regs[i])
650             continue ;
651
652         for (j = 0 ; j < sym2->nRegs ;j++ ) {
653             if (!sym2->regs[j])
654                 continue ;
655
656             if (sym2->regs[j] == sym1->regs[i])
657                 return TRUE ;
658         }
659     }
660
661     return FALSE ;
662 }
663
664 /*-----------------------------------------------------------------*/
665 /* operandsEqu - equivalent                                        */
666 /*-----------------------------------------------------------------*/
667 static bool operandsEqu ( operand *op1, operand *op2)
668 {
669     symbol *sym1, *sym2;
670
671     /* if they not symbols */
672     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
673         return FALSE;
674
675     sym1 = OP_SYMBOL(op1);
676     sym2 = OP_SYMBOL(op2);
677
678     /* if both are itemps & one is spilt
679        and the other is not then false */
680     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
681         sym1->isspilt != sym2->isspilt )
682         return FALSE ;
683
684     /* if they are the same */
685     if (sym1 == sym2)
686         return TRUE ;
687
688     if (strcmp(sym1->rname,sym2->rname) == 0)
689         return TRUE;
690
691
692     /* if left is a tmp & right is not */
693     if (IS_ITEMP(op1)  && 
694         !IS_ITEMP(op2) &&
695         sym1->isspilt  &&
696         (sym1->usl.spillLoc == sym2))
697         return TRUE;
698
699     if (IS_ITEMP(op2)  && 
700         !IS_ITEMP(op1) &&
701         sym2->isspilt  &&
702         sym1->level > 0 &&
703         (sym2->usl.spillLoc == sym1))
704         return TRUE ;
705
706     return FALSE ;
707 }
708
709 /*-----------------------------------------------------------------*/
710 /* pic14_sameRegs - two asmops have the same registers                   */
711 /*-----------------------------------------------------------------*/
712 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
713 {
714     int i;
715
716     if (aop1 == aop2)
717         return TRUE ;
718
719     if (aop1->type != AOP_REG ||
720         aop2->type != AOP_REG )
721         return FALSE ;
722
723     if (aop1->size != aop2->size )
724         return FALSE ;
725
726     for (i = 0 ; i < aop1->size ; i++ )
727         if (aop1->aopu.aop_reg[i] !=
728             aop2->aopu.aop_reg[i] )
729             return FALSE ;
730
731     return TRUE ;
732 }
733
734 /*-----------------------------------------------------------------*/
735 /* aopOp - allocates an asmop for an operand  :                    */
736 /*-----------------------------------------------------------------*/
737 void aopOp (operand *op, iCode *ic, bool result)
738 {
739     asmop *aop;
740     symbol *sym;
741     int i;
742
743     if (!op)
744         return ;
745
746     //    DEBUGpic14_emitcode(";","%d",__LINE__);
747     /* if this a literal */
748     if (IS_OP_LITERAL(op)) {
749         op->aop = aop = newAsmop(AOP_LIT);
750         aop->aopu.aop_lit = op->operand.valOperand;
751         aop->size = getSize(operandType(op));
752         return;
753     }
754
755     {
756       sym_link *type = operandType(op);
757       if(IS_PTR_CONST(type))
758         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
759     }
760
761     /* if already has a asmop then continue */
762     if (op->aop)
763         return ;
764
765     /* if the underlying symbol has a aop */
766     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
767       DEBUGpic14_emitcode(";","%d",__LINE__);
768         op->aop = OP_SYMBOL(op)->aop;
769         return;
770     }
771
772     /* if this is a true symbol */
773     if (IS_TRUE_SYMOP(op)) {    
774       //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
775       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
776       return ;
777     }
778
779     /* this is a temporary : this has
780     only four choices :
781     a) register
782     b) spillocation
783     c) rematerialize 
784     d) conditional   
785     e) can be a return use only */
786
787     sym = OP_SYMBOL(op);
788
789
790     /* if the type is a conditional */
791     if (sym->regType == REG_CND) {
792         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
793         aop->size = 0;
794         return;
795     }
796
797     /* if it is spilt then two situations
798     a) is rematerialize 
799     b) has a spill location */
800     if (sym->isspilt || sym->nRegs == 0) {
801
802       DEBUGpic14_emitcode(";","%d",__LINE__);
803         /* rematerialize it NOW */
804         if (sym->remat) {
805
806             sym->aop = op->aop = aop =
807                                       aopForRemat (op);
808             aop->size = getSize(sym->type);
809             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
810             return;
811         }
812
813         if (sym->accuse) {
814             int i;
815             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
816             aop->size = getSize(sym->type);
817             for ( i = 0 ; i < 2 ; i++ )
818                 aop->aopu.aop_str[i] = accUse[i];
819             DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
820             return;  
821         }
822
823         if (sym->ruonly ) {
824           if(sym->isptr) {  // && sym->uptr 
825             aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
826             aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
827
828             //PCOI(aop->aopu.pcop)->_const = 0;
829             //PCOI(aop->aopu.pcop)->index = 0;
830             /*
831               DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
832               __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
833             */
834             //allocDirReg (IC_LEFT(ic));
835
836             aop->size = getSize(sym->type);
837             DEBUGpic14_emitcode(";","%d",__LINE__);
838             return;
839
840           } else {
841
842             unsigned i;
843
844             aop = op->aop = sym->aop = newAsmop(AOP_STR);
845             aop->size = getSize(sym->type);
846             for ( i = 0 ; i < fReturnSizePic ; i++ )
847               aop->aopu.aop_str[i] = fReturn[i];
848
849             DEBUGpic14_emitcode(";","%d",__LINE__);
850             return;
851           }
852         }
853
854         /* else spill location  */
855         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
856             /* force a new aop if sizes differ */
857             sym->usl.spillLoc->aop = NULL;
858         }
859         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
860                             __FUNCTION__,__LINE__,
861                             sym->usl.spillLoc->rname,
862                             sym->rname, sym->usl.spillLoc->offset);
863
864         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
865         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
866         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
867                                           getSize(sym->type), 
868                                           sym->usl.spillLoc->offset);
869         aop->size = getSize(sym->type);
870
871         return;
872     }
873
874     {
875       sym_link *type = operandType(op);
876       if(IS_PTR_CONST(type)) 
877         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
878     }
879
880     /* must be in a register */
881     DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
882     sym->aop = op->aop = aop = newAsmop(AOP_REG);
883     aop->size = sym->nRegs;
884     for ( i = 0 ; i < sym->nRegs ;i++)
885         aop->aopu.aop_reg[i] = sym->regs[i];
886 }
887
888 /*-----------------------------------------------------------------*/
889 /* freeAsmop - free up the asmop given to an operand               */
890 /*----------------------------------------------------------------*/
891 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
892 {   
893     asmop *aop ;
894
895     if (!op)
896         aop = aaop;
897     else 
898         aop = op->aop;
899
900     if (!aop)
901         return ;
902
903     if (aop->freed)
904         goto dealloc; 
905
906     aop->freed = 1;
907
908     /* depending on the asmop type only three cases need work AOP_RO
909        , AOP_R1 && AOP_STK */
910 #if 0
911     switch (aop->type) {
912         case AOP_R0 :
913             if (_G.r0Pushed ) {
914                 if (pop) {
915                     pic14_emitcode ("pop","ar0");     
916                     _G.r0Pushed--;
917                 }
918             }
919             bitVectUnSetBit(ic->rUsed,R0_IDX);
920             break;
921
922         case AOP_R1 :
923             if (_G.r1Pushed ) {
924                 if (pop) {
925                     pic14_emitcode ("pop","ar1");
926                     _G.r1Pushed--;
927                 }
928             }
929             bitVectUnSetBit(ic->rUsed,R1_IDX);          
930             break;
931
932         case AOP_STK :
933         {
934             int sz = aop->size;    
935             int stk = aop->aopu.aop_stk + aop->size;
936             bitVectUnSetBit(ic->rUsed,R0_IDX);
937             bitVectUnSetBit(ic->rUsed,R1_IDX);          
938
939             getFreePtr(ic,&aop,FALSE);
940             
941             if (options.stack10bit)
942             {
943                 /* I'm not sure what to do here yet... */
944                 /* #STUB */
945                 fprintf(stderr, 
946                         "*** Warning: probably generating bad code for "
947                         "10 bit stack mode.\n");
948             }
949             
950             if (stk) {
951                 pic14_emitcode ("mov","a,_bp");
952                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
953                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
954             } else {
955                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
956             }
957
958             while (sz--) {
959                 pic14_emitcode("pop","acc");
960                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
961                 if (!sz) break;
962                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
963             }
964             op->aop = aop;
965             freeAsmop(op,NULL,ic,TRUE);
966             if (_G.r0Pushed) {
967                 pic14_emitcode("pop","ar0");
968                 _G.r0Pushed--;
969             }
970
971             if (_G.r1Pushed) {
972                 pic14_emitcode("pop","ar1");
973                 _G.r1Pushed--;
974             }       
975         }
976     }
977 #endif
978
979 dealloc:
980     /* all other cases just dealloc */
981     if (op ) {
982         op->aop = NULL;
983         if (IS_SYMOP(op)) {
984             OP_SYMBOL(op)->aop = NULL;    
985             /* if the symbol has a spill */
986             if (SPIL_LOC(op))
987                 SPIL_LOC(op)->aop = NULL;
988         }
989     }
990 }
991
992 /*-----------------------------------------------------------------*/
993 /* aopGet - for fetching value of the aop                          */
994 /*-----------------------------------------------------------------*/
995 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
996 {
997     char *s = buffer ;
998     char *rs;
999
1000     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1001     /* offset is greater than
1002     size then zero */
1003     if (offset > (aop->size - 1) &&
1004         aop->type != AOP_LIT)
1005         return zero;
1006
1007     /* depending on type */
1008     switch (aop->type) {
1009         
1010     case AOP_R0:
1011     case AOP_R1:
1012         DEBUGpic14_emitcode(";","%d",__LINE__);
1013         /* if we need to increment it */       
1014         while (offset > aop->coff) {        
1015             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1016             aop->coff++;
1017         }
1018         
1019         while (offset < aop->coff) {
1020             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1021             aop->coff--;
1022         }
1023         
1024         aop->coff = offset ;
1025         if (aop->paged) {
1026             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1027             return (dname ? "acc" : "a");
1028         }       
1029         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1030         rs = Safe_calloc(1,strlen(s)+1);
1031         strcpy(rs,s);   
1032         return rs;
1033         
1034     case AOP_DPTR:
1035     case AOP_DPTR2:
1036         DEBUGpic14_emitcode(";","%d",__LINE__);
1037     if (aop->type == AOP_DPTR2)
1038     {
1039         genSetDPTR(1);
1040     }
1041     
1042         while (offset > aop->coff) {
1043             pic14_emitcode ("inc","dptr");
1044             aop->coff++;
1045         }
1046         
1047         while (offset < aop->coff) {        
1048             pic14_emitcode("lcall","__decdptr");
1049             aop->coff--;
1050         }
1051         
1052         aop->coff = offset;
1053         if (aop->code) {
1054             pic14_emitcode("clr","a");
1055             pic14_emitcode("movc","a,@a+dptr");
1056         }
1057     else {
1058             pic14_emitcode("movx","a,@dptr");
1059     }
1060             
1061     if (aop->type == AOP_DPTR2)
1062     {
1063         genSetDPTR(0);
1064     }
1065             
1066     return (dname ? "acc" : "a");
1067         
1068         
1069     case AOP_IMMD:
1070         if (bit16) 
1071             sprintf (s,"%s",aop->aopu.aop_immd);
1072         else
1073             if (offset) 
1074                 sprintf(s,"(%s >> %d)",
1075                         aop->aopu.aop_immd,
1076                         offset*8);
1077             else
1078                 sprintf(s,"%s",
1079                         aop->aopu.aop_immd);
1080         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1081         rs = Safe_calloc(1,strlen(s)+1);
1082         strcpy(rs,s);   
1083         return rs;
1084         
1085     case AOP_DIR:
1086       if (offset) {
1087         sprintf(s,"(%s + %d)",
1088                 aop->aopu.aop_dir,
1089                 offset);
1090         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1091       } else
1092             sprintf(s,"%s",aop->aopu.aop_dir);
1093         rs = Safe_calloc(1,strlen(s)+1);
1094         strcpy(rs,s);   
1095         return rs;
1096         
1097     case AOP_REG:
1098       //if (dname) 
1099       //    return aop->aopu.aop_reg[offset]->dname;
1100       //else
1101             return aop->aopu.aop_reg[offset]->name;
1102         
1103     case AOP_CRY:
1104       //pic14_emitcode(";","%d",__LINE__);
1105       return aop->aopu.aop_dir;
1106         
1107     case AOP_ACC:
1108         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1109         return "AOP_accumulator_bug";
1110
1111     case AOP_LIT:
1112         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1113         rs = Safe_calloc(1,strlen(s)+1);
1114         strcpy(rs,s);   
1115         return rs;
1116         
1117     case AOP_STR:
1118         aop->coff = offset ;
1119         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1120             dname)
1121             return "acc";
1122         DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1123         
1124         return aop->aopu.aop_str[offset];
1125         
1126     case AOP_PCODE:
1127       {
1128         pCodeOp *pcop = aop->aopu.pcop;
1129         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1130         if(pcop->name) {
1131           DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1132           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1133           sprintf(s,"%s", pcop->name);
1134         } else
1135           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1136
1137       }
1138       rs = Safe_calloc(1,strlen(s)+1);
1139       strcpy(rs,s);   
1140       return rs;
1141
1142     }
1143
1144     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1145            "aopget got unsupported aop->type");
1146     exit(0);
1147 }
1148
1149
1150 /*-----------------------------------------------------------------*/
1151 /* popGetTempReg - create a new temporary pCodeOp                  */
1152 /*-----------------------------------------------------------------*/
1153 pCodeOp *popGetTempReg(void)
1154 {
1155
1156   pCodeOp *pcop;
1157
1158   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1159   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1160     PCOR(pcop)->r->wasUsed=1;
1161     PCOR(pcop)->r->isFree=0;
1162   }
1163
1164   return pcop;
1165 }
1166
1167 /*-----------------------------------------------------------------*/
1168 /* popGetTempReg - create a new temporary pCodeOp                  */
1169 /*-----------------------------------------------------------------*/
1170 void popReleaseTempReg(pCodeOp *pcop)
1171 {
1172
1173   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1174     PCOR(pcop)->r->isFree = 1;
1175
1176 }
1177 /*-----------------------------------------------------------------*/
1178 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1179 /*-----------------------------------------------------------------*/
1180 pCodeOp *popGetLabel(unsigned int key)
1181 {
1182
1183   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1184
1185   if(key>(unsigned int)max_key)
1186     max_key = key;
1187
1188   return newpCodeOpLabel(NULL,key+100+labelOffset);
1189 }
1190
1191 /*-------------------------------------------------------------------*/
1192 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1193 /*-------------------------------------------------------------------*/
1194 pCodeOp *popGetHighLabel(unsigned int key)
1195 {
1196   pCodeOp *pcop;
1197   pcop = popGetLabel(key);
1198   PCOLAB(pcop)->offset = 1;
1199   return pcop;
1200 }
1201
1202 /*-----------------------------------------------------------------*/
1203 /* popGet - asm operator to pcode operator conversion              */
1204 /*-----------------------------------------------------------------*/
1205 pCodeOp *popGetLit(unsigned int lit)
1206 {
1207
1208   return newpCodeOpLit(lit);
1209 }
1210
1211
1212 /*-----------------------------------------------------------------*/
1213 /* popGetImmd - asm operator to pcode immediate conversion         */
1214 /*-----------------------------------------------------------------*/
1215 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1216 {
1217
1218   return newpCodeOpImmd(name, offset,index, 0, is_func);
1219 }
1220
1221
1222 /*-----------------------------------------------------------------*/
1223 /* popGet - asm operator to pcode operator conversion              */
1224 /*-----------------------------------------------------------------*/
1225 pCodeOp *popGetWithString(char *str, int isExtern)
1226 {
1227   pCodeOp *pcop;
1228
1229
1230   if(!str) {
1231     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1232     exit (1);
1233   }
1234
1235   pcop = newpCodeOp(str,PO_STR);
1236   PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1237
1238   return pcop;
1239 }
1240
1241 /*-----------------------------------------------------------------*/
1242 /* popRegFromString -                                              */
1243 /*-----------------------------------------------------------------*/
1244 pCodeOp *popRegFromString(char *str, int size, int offset)
1245 {
1246
1247   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1248   pcop->type = PO_DIR;
1249
1250   DEBUGpic14_emitcode(";","%d",__LINE__);
1251
1252   if(!str)
1253     str = "BAD_STRING";
1254
1255   pcop->name = Safe_calloc(1,strlen(str)+1);
1256   strcpy(pcop->name,str);
1257
1258   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1259
1260   PCOR(pcop)->r = dirregWithName(pcop->name);
1261   if(PCOR(pcop)->r == NULL) {
1262     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1263     PCOR(pcop)->r = allocRegByName (pcop->name,size);
1264     DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1265   } else {
1266     DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1267   }
1268   PCOR(pcop)->instance = offset;
1269
1270   return pcop;
1271 }
1272
1273 /*-----------------------------------------------------------------*/
1274 /*-----------------------------------------------------------------*/
1275 pCodeOp *popRegFromIdx(int rIdx)
1276 {
1277   pCodeOp *pcop;
1278
1279   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1280                        __FUNCTION__,__LINE__,rIdx);
1281
1282   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1283
1284   PCOR(pcop)->rIdx = rIdx;
1285   PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1286   PCOR(pcop)->r->isFree = 0;
1287   PCOR(pcop)->r->wasUsed = 1;
1288
1289   pcop->type = PCOR(pcop)->r->pc_type;
1290
1291
1292   return pcop;
1293 }
1294
1295 /*-----------------------------------------------------------------*/
1296 /* popGet - asm operator to pcode operator conversion              */
1297 /*-----------------------------------------------------------------*/
1298 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1299 {
1300   //char *s = buffer ;
1301     //char *rs;
1302
1303     pCodeOp *pcop;
1304
1305     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1306     /* offset is greater than
1307     size then zero */
1308
1309     if (offset > (aop->size - 1) &&
1310         aop->type != AOP_LIT)
1311       return NULL;  //zero;
1312
1313     /* depending on type */
1314     switch (aop->type) {
1315         
1316     case AOP_R0:
1317     case AOP_R1:
1318     case AOP_DPTR:
1319     case AOP_DPTR2:
1320     case AOP_ACC:
1321         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1322         return NULL;
1323         
1324     case AOP_IMMD:
1325       DEBUGpic14_emitcode(";","%d",__LINE__);
1326       return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1327
1328     case AOP_DIR:
1329       return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1330 #if 0
1331         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1332         pcop->type = PO_DIR;
1333
1334         /*
1335         if (offset)
1336             sprintf(s,"(%s + %d)",
1337                     aop->aopu.aop_dir,
1338                     offset);
1339         else
1340             sprintf(s,"%s",aop->aopu.aop_dir);
1341         pcop->name = Safe_calloc(1,strlen(s)+1);
1342         strcpy(pcop->name,s);   
1343         */
1344         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1345         strcpy(pcop->name,aop->aopu.aop_dir);   
1346         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1347         if(PCOR(pcop)->r == NULL) {
1348           //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1349           PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1350           DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1351         } else {
1352           DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1353         }
1354         PCOR(pcop)->instance = offset;
1355
1356         return pcop;
1357 #endif
1358         
1359     case AOP_REG:
1360       {
1361         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1362
1363         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1364         PCOR(pcop)->rIdx = rIdx;
1365         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1366         PCOR(pcop)->r->wasUsed=1;
1367         PCOR(pcop)->r->isFree=0;
1368
1369         PCOR(pcop)->instance = offset;
1370         pcop->type = PCOR(pcop)->r->pc_type;
1371         //rs = aop->aopu.aop_reg[offset]->name;
1372         DEBUGpic14_emitcode(";","%d regiser idx = %d ",__LINE__,rIdx);
1373         return pcop;
1374       }
1375
1376     case AOP_CRY:
1377       pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1378       PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1379       //if(PCOR(pcop)->r == NULL)
1380       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1381       return pcop;
1382         
1383     case AOP_LIT:
1384       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1385
1386     case AOP_STR:
1387       DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1388       return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1389       /*
1390       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1391       PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1392       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1393       pcop->type = PCOR(pcop)->r->pc_type;
1394       pcop->name = PCOR(pcop)->r->name;
1395
1396       return pcop;
1397       */
1398
1399     case AOP_PCODE:
1400       DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s) %d %s",pCodeOpType(aop->aopu.pcop),
1401                           __LINE__, 
1402                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1403       pcop = pCodeOpCopy(aop->aopu.pcop);
1404       PCOI(pcop)->offset = offset;
1405       return pcop;
1406     }
1407
1408     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1409            "popGet got unsupported aop->type");
1410     exit(0);
1411 }
1412 /*-----------------------------------------------------------------*/
1413 /* aopPut - puts a string for a aop                                */
1414 /*-----------------------------------------------------------------*/
1415 void aopPut (asmop *aop, char *s, int offset)
1416 {
1417     char *d = buffer ;
1418     symbol *lbl ;
1419
1420     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1421
1422     if (aop->size && offset > ( aop->size - 1)) {
1423         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1424                "aopPut got offset > aop->size");
1425         exit(0);
1426     }
1427
1428     /* will assign value to value */
1429     /* depending on where it is ofcourse */
1430     switch (aop->type) {
1431     case AOP_DIR:
1432       if (offset) {
1433         sprintf(d,"(%s + %d)",
1434                 aop->aopu.aop_dir,offset);
1435         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1436
1437       } else
1438             sprintf(d,"%s",aop->aopu.aop_dir);
1439         
1440         if (strcmp(d,s)) {
1441           DEBUGpic14_emitcode(";","%d",__LINE__);
1442           if(strcmp(s,"W"))
1443             pic14_emitcode("movf","%s,w",s);
1444           pic14_emitcode("movwf","%s",d);
1445
1446           if(strcmp(s,"W")) {
1447             pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1448             if(offset >= aop->size) {
1449               emitpcode(POC_CLRF,popGet(aop,offset));
1450               break;
1451             } else
1452               emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1453           }
1454
1455           emitpcode(POC_MOVWF,popGet(aop,offset));
1456
1457
1458         }
1459         break;
1460         
1461     case AOP_REG:
1462       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1463         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1464           /*
1465             if (*s == '@'           ||
1466                 strcmp(s,"r0") == 0 ||
1467                 strcmp(s,"r1") == 0 ||
1468                 strcmp(s,"r2") == 0 ||
1469                 strcmp(s,"r3") == 0 ||
1470                 strcmp(s,"r4") == 0 ||
1471                 strcmp(s,"r5") == 0 ||
1472                 strcmp(s,"r6") == 0 || 
1473                 strcmp(s,"r7") == 0 )
1474                 pic14_emitcode("mov","%s,%s  ; %d",
1475                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1476             else
1477           */
1478
1479           if(strcmp(s,"W")==0 )
1480             pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1481
1482           pic14_emitcode("movwf","%s",
1483                    aop->aopu.aop_reg[offset]->name);
1484
1485           if(strcmp(s,zero)==0) {
1486             emitpcode(POC_CLRF,popGet(aop,offset));
1487
1488           } else if(strcmp(s,"W")==0) {
1489             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1490             pcop->type = PO_GPR_REGISTER;
1491
1492             PCOR(pcop)->rIdx = -1;
1493             PCOR(pcop)->r = NULL;
1494
1495             DEBUGpic14_emitcode(";","%d",__LINE__);
1496             pcop->name = Safe_strdup(s);
1497             emitpcode(POC_MOVFW,pcop);
1498             emitpcode(POC_MOVWF,popGet(aop,offset));
1499           } else if(strcmp(s,one)==0) {
1500             emitpcode(POC_CLRF,popGet(aop,offset));
1501             emitpcode(POC_INCF,popGet(aop,offset));
1502           } else {
1503             emitpcode(POC_MOVWF,popGet(aop,offset));
1504           }
1505         }
1506         break;
1507         
1508     case AOP_DPTR:
1509     case AOP_DPTR2:
1510     
1511     if (aop->type == AOP_DPTR2)
1512     {
1513         genSetDPTR(1);
1514     }
1515     
1516         if (aop->code) {
1517             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1518                    "aopPut writting to code space");
1519             exit(0);
1520         }
1521         
1522         while (offset > aop->coff) {
1523             aop->coff++;
1524             pic14_emitcode ("inc","dptr");
1525         }
1526         
1527         while (offset < aop->coff) {
1528             aop->coff-- ;
1529             pic14_emitcode("lcall","__decdptr");
1530         }
1531         
1532         aop->coff = offset;
1533         
1534         /* if not in accumulater */
1535         MOVA(s);        
1536         
1537         pic14_emitcode ("movx","@dptr,a");
1538         
1539     if (aop->type == AOP_DPTR2)
1540     {
1541         genSetDPTR(0);
1542     }
1543         break;
1544         
1545     case AOP_R0:
1546     case AOP_R1:
1547         while (offset > aop->coff) {
1548             aop->coff++;
1549             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1550         }
1551         while (offset < aop->coff) {
1552             aop->coff-- ;
1553             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1554         }
1555         aop->coff = offset;
1556         
1557         if (aop->paged) {
1558             MOVA(s);           
1559             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1560             
1561         } else
1562             if (*s == '@') {
1563                 MOVA(s);
1564                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1565             } else
1566                 if (strcmp(s,"r0") == 0 ||
1567                     strcmp(s,"r1") == 0 ||
1568                     strcmp(s,"r2") == 0 ||
1569                     strcmp(s,"r3") == 0 ||
1570                     strcmp(s,"r4") == 0 ||
1571                     strcmp(s,"r5") == 0 ||
1572                     strcmp(s,"r6") == 0 || 
1573                     strcmp(s,"r7") == 0 ) {
1574                     char buffer[10];
1575                     sprintf(buffer,"a%s",s);
1576                     pic14_emitcode("mov","@%s,%s",
1577                              aop->aopu.aop_ptr->name,buffer);
1578                 } else
1579                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1580         
1581         break;
1582         
1583     case AOP_STK:
1584         if (strcmp(s,"a") == 0)
1585             pic14_emitcode("push","acc");
1586         else
1587             pic14_emitcode("push","%s",s);
1588         
1589         break;
1590         
1591     case AOP_CRY:
1592         /* if bit variable */
1593         if (!aop->aopu.aop_dir) {
1594             pic14_emitcode("clr","a");
1595             pic14_emitcode("rlc","a");
1596         } else {
1597             if (s == zero) 
1598                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1599             else
1600                 if (s == one)
1601                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1602                 else
1603                     if (!strcmp(s,"c"))
1604                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1605                     else {
1606                         lbl = newiTempLabel(NULL);
1607                         
1608                         if (strcmp(s,"a")) {
1609                             MOVA(s);
1610                         }
1611                         pic14_emitcode("clr","c");
1612                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1613                         pic14_emitcode("cpl","c");
1614                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1615                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1616                     }
1617         }
1618         break;
1619         
1620     case AOP_STR:
1621         aop->coff = offset;
1622         if (strcmp(aop->aopu.aop_str[offset],s))
1623             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1624         break;
1625         
1626     case AOP_ACC:
1627         aop->coff = offset;
1628         if (!offset && (strcmp(s,"acc") == 0))
1629             break;
1630         
1631         if (strcmp(aop->aopu.aop_str[offset],s))
1632             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1633         break;
1634
1635     default :
1636         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1637                "aopPut got unsupported aop->type");
1638         exit(0);    
1639     }    
1640
1641 }
1642
1643 /*-----------------------------------------------------------------*/
1644 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1645 /*-----------------------------------------------------------------*/
1646 void mov2w (asmop *aop, int offset)
1647 {
1648
1649   if(!aop)
1650     return;
1651
1652   DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1653
1654   if ( aop->type == AOP_PCODE ||
1655        aop->type == AOP_LIT ||
1656        aop->type == AOP_IMMD )
1657     emitpcode(POC_MOVLW,popGet(aop,offset));
1658   else
1659     emitpcode(POC_MOVFW,popGet(aop,offset));
1660
1661 }
1662
1663 /*-----------------------------------------------------------------*/
1664 /* reAdjustPreg - points a register back to where it should        */
1665 /*-----------------------------------------------------------------*/
1666 static void reAdjustPreg (asmop *aop)
1667 {
1668     int size ;
1669
1670     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1671     aop->coff = 0;
1672     if ((size = aop->size) <= 1)
1673         return ;
1674     size-- ;
1675     switch (aop->type) {
1676         case AOP_R0 :
1677         case AOP_R1 :
1678             while (size--)
1679                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1680             break;          
1681         case AOP_DPTR :
1682         case AOP_DPTR2:
1683             if (aop->type == AOP_DPTR2)
1684             {
1685                 genSetDPTR(1);
1686             } 
1687             while (size--)
1688             {
1689                 pic14_emitcode("lcall","__decdptr");
1690             }
1691                 
1692             if (aop->type == AOP_DPTR2)
1693             {
1694                 genSetDPTR(0);
1695             }                
1696             break;  
1697
1698     }   
1699
1700 }
1701
1702
1703 #if 0
1704 /*-----------------------------------------------------------------*/
1705 /* opIsGptr: returns non-zero if the passed operand is             */   
1706 /* a generic pointer type.                                         */
1707 /*-----------------------------------------------------------------*/ 
1708 static int opIsGptr(operand *op)
1709 {
1710     sym_link *type = operandType(op);
1711     
1712     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1713     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1714     {
1715         return 1;
1716     }
1717     return 0;        
1718 }
1719 #endif
1720
1721 /*-----------------------------------------------------------------*/
1722 /* pic14_getDataSize - get the operand data size                         */
1723 /*-----------------------------------------------------------------*/
1724 int pic14_getDataSize(operand *op)
1725 {
1726     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1727
1728
1729     return AOP_SIZE(op);
1730
1731     // tsd- in the pic port, the genptr size is 1, so this code here
1732     // fails. ( in the 8051 port, the size was 4).
1733 #if 0
1734     int size;
1735     size = AOP_SIZE(op);
1736     if (size == GPTRSIZE)
1737     {
1738         sym_link *type = operandType(op);
1739         if (IS_GENPTR(type))
1740         {
1741             /* generic pointer; arithmetic operations
1742              * should ignore the high byte (pointer type).
1743              */
1744             size--;
1745     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1746         }
1747     }
1748     return size;
1749 #endif
1750 }
1751
1752 /*-----------------------------------------------------------------*/
1753 /* pic14_outAcc - output Acc                                             */
1754 /*-----------------------------------------------------------------*/
1755 void pic14_outAcc(operand *result)
1756 {
1757   int size,offset;
1758   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1759   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1760
1761
1762   size = pic14_getDataSize(result);
1763   if(size){
1764     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1765     size--;
1766     offset = 1;
1767     /* unsigned or positive */
1768     while(size--)
1769       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1770   }
1771
1772 }
1773
1774 /*-----------------------------------------------------------------*/
1775 /* pic14_outBitC - output a bit C                                        */
1776 /*-----------------------------------------------------------------*/
1777 void pic14_outBitC(operand *result)
1778 {
1779
1780     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1781     /* if the result is bit */
1782     if (AOP_TYPE(result) == AOP_CRY) 
1783         aopPut(AOP(result),"c",0);
1784     else {
1785         pic14_emitcode("clr","a  ; %d", __LINE__);
1786         pic14_emitcode("rlc","a");
1787         pic14_outAcc(result);
1788     }
1789 }
1790
1791 /*-----------------------------------------------------------------*/
1792 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1793 /*-----------------------------------------------------------------*/
1794 void pic14_toBoolean(operand *oper)
1795 {
1796     int size = AOP_SIZE(oper) - 1;
1797     int offset = 1;
1798
1799     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1800
1801     if ( AOP_TYPE(oper) != AOP_ACC) {
1802       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1803     }
1804     while (size--) {
1805       emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1806     }
1807 }
1808
1809
1810 /*-----------------------------------------------------------------*/
1811 /* genNot - generate code for ! operation                          */
1812 /*-----------------------------------------------------------------*/
1813 static void genNot (iCode *ic)
1814 {
1815   symbol *tlbl;
1816   int size;
1817
1818   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1819   /* assign asmOps to operand & result */
1820   aopOp (IC_LEFT(ic),ic,FALSE);
1821   aopOp (IC_RESULT(ic),ic,TRUE);
1822
1823   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1824   /* if in bit space then a special case */
1825   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1826     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1827       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1828       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1829     } else {
1830       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1831       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1832       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1833     }
1834     goto release;
1835   }
1836
1837   size = AOP_SIZE(IC_LEFT(ic));
1838   if(size == 1) {
1839     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1840     emitpcode(POC_ANDLW,popGetLit(1));
1841     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1842     goto release;
1843   }
1844   pic14_toBoolean(IC_LEFT(ic));
1845
1846   tlbl = newiTempLabel(NULL);
1847   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1848   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1849   pic14_outBitC(IC_RESULT(ic));
1850
1851  release:    
1852   /* release the aops */
1853   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1854   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1855 }
1856
1857
1858 /*-----------------------------------------------------------------*/
1859 /* genCpl - generate code for complement                           */
1860 /*-----------------------------------------------------------------*/
1861 static void genCpl (iCode *ic)
1862 {
1863   operand *left, *result;
1864   int size, offset=0;  
1865
1866
1867   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1868   aopOp((left = IC_LEFT(ic)),ic,FALSE);
1869   aopOp((result=IC_RESULT(ic)),ic,TRUE);
1870
1871   /* if both are in bit space then 
1872      a special case */
1873   if (AOP_TYPE(result) == AOP_CRY &&
1874       AOP_TYPE(left) == AOP_CRY ) { 
1875
1876     pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1877     pic14_emitcode("cpl","c"); 
1878     pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1879     goto release; 
1880   } 
1881
1882   size = AOP_SIZE(result);
1883   while (size--) {
1884
1885     if(AOP_TYPE(left) == AOP_ACC) 
1886       emitpcode(POC_XORLW, popGetLit(0xff));
1887     else
1888       emitpcode(POC_COMFW,popGet(AOP(left),offset));
1889
1890     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1891
1892   }
1893
1894
1895 release:
1896     /* release the aops */
1897     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1898     freeAsmop(result,NULL,ic,TRUE);
1899 }
1900
1901 /*-----------------------------------------------------------------*/
1902 /* genUminusFloat - unary minus for floating points                */
1903 /*-----------------------------------------------------------------*/
1904 static void genUminusFloat(operand *op,operand *result)
1905 {
1906     int size ,offset =0 ;
1907     char *l;
1908
1909     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1910     /* for this we just need to flip the 
1911     first it then copy the rest in place */
1912     size = AOP_SIZE(op) - 1;
1913     l = aopGet(AOP(op),3,FALSE,FALSE);
1914
1915     MOVA(l);    
1916
1917     pic14_emitcode("cpl","acc.7");
1918     aopPut(AOP(result),"a",3);    
1919
1920     while(size--) {
1921         aopPut(AOP(result),
1922                aopGet(AOP(op),offset,FALSE,FALSE),
1923                offset);
1924         offset++;
1925     }          
1926 }
1927
1928 /*-----------------------------------------------------------------*/
1929 /* genUminus - unary minus code generation                         */
1930 /*-----------------------------------------------------------------*/
1931 static void genUminus (iCode *ic)
1932 {
1933   int size, i;
1934   sym_link *optype, *rtype;
1935
1936
1937   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1938   /* assign asmops */
1939   aopOp(IC_LEFT(ic),ic,FALSE);
1940   aopOp(IC_RESULT(ic),ic,TRUE);
1941
1942   /* if both in bit space then special
1943      case */
1944   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1945       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1946
1947     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1948     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1949     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1950
1951     goto release; 
1952   } 
1953
1954   optype = operandType(IC_LEFT(ic));
1955   rtype = operandType(IC_RESULT(ic));
1956
1957   /* if float then do float stuff */
1958   if (IS_FLOAT(optype)) {
1959     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1960     goto release;
1961   }
1962
1963   /* otherwise subtract from zero by taking the 2's complement */
1964   size = AOP_SIZE(IC_LEFT(ic));
1965
1966   for(i=0; i<size; i++) {
1967     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1968       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1969     else {
1970       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1971       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1972     }
1973   }
1974
1975   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1976   for(i=1; i<size; i++) {
1977     emitSKPNZ;
1978     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1979   }
1980
1981  release:
1982   /* release the aops */
1983   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1984   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1985 }
1986
1987 /*-----------------------------------------------------------------*/
1988 /* saveRegisters - will look for a call and save the registers     */
1989 /*-----------------------------------------------------------------*/
1990 static void saveRegisters(iCode *lic) 
1991 {
1992     int i;
1993     iCode *ic;
1994     bitVect *rsave;
1995     sym_link *dtype;
1996
1997     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1998     /* look for call */
1999     for (ic = lic ; ic ; ic = ic->next) 
2000         if (ic->op == CALL || ic->op == PCALL)
2001             break;
2002
2003     if (!ic) {
2004         fprintf(stderr,"found parameter push with no function call\n");
2005         return ;
2006     }
2007
2008     /* if the registers have been saved already then
2009     do nothing */
2010     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2011         return ;
2012
2013     /* find the registers in use at this time 
2014     and push them away to safety */
2015     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2016                           ic->rUsed);
2017
2018     ic->regsSaved = 1;
2019     if (options.useXstack) {
2020         if (bitVectBitValue(rsave,R0_IDX))
2021             pic14_emitcode("mov","b,r0");
2022         pic14_emitcode("mov","r0,%s",spname);
2023         for (i = 0 ; i < pic14_nRegs ; i++) {
2024             if (bitVectBitValue(rsave,i)) {
2025                 if (i == R0_IDX)
2026                     pic14_emitcode("mov","a,b");
2027                 else
2028                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2029                 pic14_emitcode("movx","@r0,a");
2030                 pic14_emitcode("inc","r0");
2031             }
2032         }
2033         pic14_emitcode("mov","%s,r0",spname);
2034         if (bitVectBitValue(rsave,R0_IDX))
2035             pic14_emitcode("mov","r0,b");           
2036     }// else
2037     //for (i = 0 ; i < pic14_nRegs ; i++) {
2038     //    if (bitVectBitValue(rsave,i))
2039     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2040     //}
2041
2042     dtype = operandType(IC_LEFT(ic));
2043     if (currFunc && dtype && 
2044         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2045         IFFUNC_ISISR(currFunc->type) &&
2046         !ic->bankSaved) 
2047
2048         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2049
2050 }
2051 /*-----------------------------------------------------------------*/
2052 /* unsaveRegisters - pop the pushed registers                      */
2053 /*-----------------------------------------------------------------*/
2054 static void unsaveRegisters (iCode *ic)
2055 {
2056     int i;
2057     bitVect *rsave;
2058
2059     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2060     /* find the registers in use at this time 
2061     and push them away to safety */
2062     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2063                           ic->rUsed);
2064     
2065     if (options.useXstack) {
2066         pic14_emitcode("mov","r0,%s",spname);   
2067         for (i =  pic14_nRegs ; i >= 0 ; i--) {
2068             if (bitVectBitValue(rsave,i)) {
2069                 pic14_emitcode("dec","r0");
2070                 pic14_emitcode("movx","a,@r0");
2071                 if (i == R0_IDX)
2072                     pic14_emitcode("mov","b,a");
2073                 else
2074                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2075             }       
2076
2077         }
2078         pic14_emitcode("mov","%s,r0",spname);
2079         if (bitVectBitValue(rsave,R0_IDX))
2080             pic14_emitcode("mov","r0,b");
2081     } //else
2082     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2083     //    if (bitVectBitValue(rsave,i))
2084     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2085     //}
2086
2087 }  
2088
2089
2090 /*-----------------------------------------------------------------*/
2091 /* pushSide -                                                      */
2092 /*-----------------------------------------------------------------*/
2093 static void pushSide(operand * oper, int size)
2094 {
2095 #if 0
2096         int offset = 0;
2097     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2098         while (size--) {
2099                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2100                 if (AOP_TYPE(oper) != AOP_REG &&
2101                     AOP_TYPE(oper) != AOP_DIR &&
2102                     strcmp(l,"a") ) {
2103                         pic14_emitcode("mov","a,%s",l);
2104                         pic14_emitcode("push","acc");
2105                 } else
2106                         pic14_emitcode("push","%s",l);
2107         }
2108 #endif
2109 }
2110
2111 /*-----------------------------------------------------------------*/
2112 /* assignResultValue -                                             */
2113 /*-----------------------------------------------------------------*/
2114 static void assignResultValue(operand * oper)
2115 {
2116   int size = AOP_SIZE(oper);
2117
2118   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2119
2120   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2121
2122   while (size--) {
2123     if (GpsuedoStkPtr++)
2124       emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2125     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2126   }
2127 }
2128
2129
2130 /*-----------------------------------------------------------------*/
2131 /* genIpush - genrate code for pushing this gets a little complex  */
2132 /*-----------------------------------------------------------------*/
2133 static void genIpush (iCode *ic)
2134 {
2135
2136   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2137 #if 0
2138     int size, offset = 0 ;
2139     char *l;
2140
2141
2142     /* if this is not a parm push : ie. it is spill push 
2143     and spill push is always done on the local stack */
2144     if (!ic->parmPush) {
2145
2146         /* and the item is spilt then do nothing */
2147         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2148             return ;
2149
2150         aopOp(IC_LEFT(ic),ic,FALSE);
2151         size = AOP_SIZE(IC_LEFT(ic));
2152         /* push it on the stack */
2153         while(size--) {
2154             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2155             if (*l == '#') {
2156                 MOVA(l);
2157                 l = "acc";
2158             }
2159             pic14_emitcode("push","%s",l);
2160         }
2161         return ;        
2162     }
2163
2164     /* this is a paramter push: in this case we call
2165     the routine to find the call and save those
2166     registers that need to be saved */   
2167     saveRegisters(ic);
2168
2169     /* then do the push */
2170     aopOp(IC_LEFT(ic),ic,FALSE);
2171
2172
2173         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2174     size = AOP_SIZE(IC_LEFT(ic));
2175
2176     while (size--) {
2177         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2178         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2179             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2180             strcmp(l,"a") ) {
2181             pic14_emitcode("mov","a,%s",l);
2182             pic14_emitcode("push","acc");
2183         } else
2184             pic14_emitcode("push","%s",l);
2185     }       
2186
2187     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2188 #endif
2189 }
2190
2191 /*-----------------------------------------------------------------*/
2192 /* genIpop - recover the registers: can happen only for spilling   */
2193 /*-----------------------------------------------------------------*/
2194 static void genIpop (iCode *ic)
2195 {
2196   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2197 #if 0
2198     int size,offset ;
2199
2200
2201     /* if the temp was not pushed then */
2202     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2203         return ;
2204
2205     aopOp(IC_LEFT(ic),ic,FALSE);
2206     size = AOP_SIZE(IC_LEFT(ic));
2207     offset = (size-1);
2208     while (size--) 
2209         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2210                                    FALSE,TRUE));
2211
2212     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2213 #endif
2214 }
2215
2216 /*-----------------------------------------------------------------*/
2217 /* unsaverbank - restores the resgister bank from stack            */
2218 /*-----------------------------------------------------------------*/
2219 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2220 {
2221   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2222 #if 0
2223     int i;
2224     asmop *aop ;
2225     regs *r = NULL;
2226
2227     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2228     if (popPsw) {
2229         if (options.useXstack) {
2230             aop = newAsmop(0);
2231             r = getFreePtr(ic,&aop,FALSE);
2232             
2233             
2234             pic14_emitcode("mov","%s,_spx",r->name);
2235             pic14_emitcode("movx","a,@%s",r->name);
2236             pic14_emitcode("mov","psw,a");
2237             pic14_emitcode("dec","%s",r->name);
2238             
2239         }else
2240             pic14_emitcode ("pop","psw");
2241     }
2242
2243     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2244         if (options.useXstack) {       
2245             pic14_emitcode("movx","a,@%s",r->name);
2246             //pic14_emitcode("mov","(%s+%d),a",
2247             //       regspic14[i].base,8*bank+regspic14[i].offset);
2248             pic14_emitcode("dec","%s",r->name);
2249
2250         } else 
2251           pic14_emitcode("pop",""); //"(%s+%d)",
2252         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2253     }
2254
2255     if (options.useXstack) {
2256
2257         pic14_emitcode("mov","_spx,%s",r->name);
2258         freeAsmop(NULL,aop,ic,TRUE);
2259
2260     }
2261 #endif 
2262 }
2263
2264 /*-----------------------------------------------------------------*/
2265 /* saverbank - saves an entire register bank on the stack          */
2266 /*-----------------------------------------------------------------*/
2267 static void saverbank (int bank, iCode *ic, bool pushPsw)
2268 {
2269   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2270 #if 0
2271     int i;
2272     asmop *aop ;
2273     regs *r = NULL;
2274
2275     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2276     if (options.useXstack) {
2277
2278         aop = newAsmop(0);
2279         r = getFreePtr(ic,&aop,FALSE);  
2280         pic14_emitcode("mov","%s,_spx",r->name);
2281
2282     }
2283
2284     for (i = 0 ; i < pic14_nRegs ;i++) {
2285         if (options.useXstack) {
2286             pic14_emitcode("inc","%s",r->name);
2287             //pic14_emitcode("mov","a,(%s+%d)",
2288             //         regspic14[i].base,8*bank+regspic14[i].offset);
2289             pic14_emitcode("movx","@%s,a",r->name);           
2290         } else 
2291           pic14_emitcode("push","");// "(%s+%d)",
2292                      //regspic14[i].base,8*bank+regspic14[i].offset);
2293     }
2294     
2295     if (pushPsw) {
2296         if (options.useXstack) {
2297             pic14_emitcode("mov","a,psw");
2298             pic14_emitcode("movx","@%s,a",r->name);     
2299             pic14_emitcode("inc","%s",r->name);
2300             pic14_emitcode("mov","_spx,%s",r->name);       
2301             freeAsmop (NULL,aop,ic,TRUE);
2302             
2303         } else
2304             pic14_emitcode("push","psw");
2305         
2306         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2307     }
2308     ic->bankSaved = 1;
2309 #endif
2310 }
2311
2312 /*-----------------------------------------------------------------*/
2313 /* genCall - generates a call statement                            */
2314 /*-----------------------------------------------------------------*/
2315 static void genCall (iCode *ic)
2316 {
2317   sym_link *dtype;   
2318   symbol *sym;
2319   unsigned char *name;
2320   int isExtern;
2321
2322   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2323
2324   /* if caller saves & we have not saved then */
2325   if (!ic->regsSaved)
2326     saveRegisters(ic);
2327
2328   /* if we are calling a function that is not using
2329      the same register bank then we need to save the
2330      destination registers on the stack */
2331   dtype = operandType(IC_LEFT(ic));
2332   if (currFunc && dtype && 
2333       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2334       IFFUNC_ISISR(currFunc->type) &&
2335       !ic->bankSaved) 
2336
2337     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2338
2339   /* if send set is not empty the assign */
2340   if (_G.sendSet) {
2341     iCode *sic;
2342     /* For the Pic port, there is no data stack.
2343      * So parameters passed to functions are stored
2344      * in registers. (The pCode optimizer will get
2345      * rid of most of these :).
2346      */
2347     int psuedoStkPtr=-1;
2348     int firstTimeThruLoop = 1;
2349
2350     _G.sendSet = reverseSet(_G.sendSet);
2351
2352     /* First figure how many parameters are getting passed */
2353     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2354      sic = setNextItem(_G.sendSet)) {
2355
2356       aopOp(IC_LEFT(sic),sic,FALSE);
2357       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2358       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2359     }
2360
2361     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2362      sic = setNextItem(_G.sendSet)) {
2363       int size, offset = 0;
2364
2365       aopOp(IC_LEFT(sic),sic,FALSE);
2366       size = AOP_SIZE(IC_LEFT(sic));
2367
2368       while (size--) {
2369         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2370              AopType(AOP_TYPE(IC_LEFT(sic))));
2371
2372         if(!firstTimeThruLoop) {
2373           /* If this is not the first time we've been through the loop
2374            * then we need to save the parameter in a temporary
2375            * register. The last byte of the last parameter is
2376            * passed in W. */
2377           emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2378
2379         }
2380         firstTimeThruLoop=0;
2381
2382         mov2w (AOP(IC_LEFT(sic)),  offset);
2383         offset++;
2384       }
2385       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2386     }
2387     _G.sendSet = NULL;
2388   }
2389   /* make the call */
2390   sym = OP_SYMBOL(IC_LEFT(ic));
2391   name = sym->rname[0] ? sym->rname : sym->name;
2392   isExtern = IS_EXTERN(sym->etype);
2393   if (isExtern) {
2394         emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2395   }
2396   emitpcode(POC_CALL,popGetWithString(name,isExtern));
2397   if (isExtern) {
2398         emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel */
2399   }
2400   GpsuedoStkPtr=0;
2401   /* if we need assign a result value */
2402   if ((IS_ITEMP(IC_RESULT(ic)) && 
2403        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2404         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2405       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2406
2407     _G.accInUse++;
2408     aopOp(IC_RESULT(ic),ic,FALSE);
2409     _G.accInUse--;
2410
2411     assignResultValue(IC_RESULT(ic));
2412
2413     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2414                          AopType(AOP_TYPE(IC_RESULT(ic))));
2415                 
2416     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2417   }
2418
2419   /* adjust the stack for parameters if 
2420      required */
2421   if (ic->parmBytes) {
2422     int i;
2423     if (ic->parmBytes > 3) {
2424       pic14_emitcode("mov","a,%s",spname);
2425       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2426       pic14_emitcode("mov","%s,a",spname);
2427     } else 
2428       for ( i = 0 ; i <  ic->parmBytes ;i++)
2429         pic14_emitcode("dec","%s",spname);
2430
2431   }
2432
2433   /* if register bank was saved then pop them */
2434   if (ic->bankSaved)
2435     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2436
2437   /* if we hade saved some registers then unsave them */
2438   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2439     unsaveRegisters (ic);
2440
2441
2442 }
2443
2444 /*-----------------------------------------------------------------*/
2445 /* genPcall - generates a call by pointer statement                */
2446 /*-----------------------------------------------------------------*/
2447 static void genPcall (iCode *ic)
2448 {
2449     sym_link *dtype;
2450     symbol *albl = newiTempLabel(NULL);
2451     symbol *blbl = newiTempLabel(NULL);
2452     PIC_OPCODE poc;
2453         pCodeOp *pcop;
2454     operand *left;
2455
2456     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2457     /* if caller saves & we have not saved then */
2458     if (!ic->regsSaved)
2459         saveRegisters(ic);
2460
2461     /* if we are calling a function that is not using
2462     the same register bank then we need to save the
2463     destination registers on the stack */
2464     dtype = operandType(IC_LEFT(ic));
2465     if (currFunc && dtype && 
2466         IFFUNC_ISISR(currFunc->type) &&
2467         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2468         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2469
2470     left = IC_LEFT(ic);
2471     aopOp(left,ic,FALSE);
2472     DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2473
2474     pushSide(IC_LEFT(ic), FPTRSIZE);
2475
2476     /* if send set is not empty, assign parameters */
2477     if (_G.sendSet) {
2478
2479         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2480         /* no way to pass args - W always gets used to make the call */
2481     }
2482 /* first idea - factor out a common helper function and call it.
2483    But don't know how to get it generated only once in its own block
2484
2485     if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2486             char *rname;
2487             char *buffer;
2488             rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2489             DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2490             buffer = Safe_calloc(1,strlen(rname)+16);
2491             sprintf(buffer, "%s_goto_helper", rname);
2492             addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2493             free(buffer);
2494     }
2495 */
2496     emitpcode(POC_CALL,popGetLabel(albl->key));
2497         pcop = popGetLabel(blbl->key);
2498         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2499     emitpcode(POC_GOTO,pcop);
2500     emitpLabel(albl->key);
2501
2502     poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
2503     
2504     emitpcode(poc,popGet(AOP(left),1));
2505     emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2506     emitpcode(poc,popGet(AOP(left),0));
2507     emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2508
2509     emitpLabel(blbl->key);
2510
2511     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2512
2513     /* if we need to assign a result value */
2514     if ((IS_ITEMP(IC_RESULT(ic)) &&
2515          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2516           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2517         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2518
2519         _G.accInUse++;
2520         aopOp(IC_RESULT(ic),ic,FALSE);
2521         _G.accInUse--;
2522         
2523         assignResultValue(IC_RESULT(ic));
2524
2525         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2526     }
2527
2528     /* if register bank was saved then unsave them */
2529     if (currFunc && dtype && 
2530         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2531         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2532
2533     /* if we hade saved some registers then
2534     unsave them */
2535     if (ic->regsSaved)
2536         unsaveRegisters (ic);
2537
2538 }
2539
2540 /*-----------------------------------------------------------------*/
2541 /* resultRemat - result  is rematerializable                       */
2542 /*-----------------------------------------------------------------*/
2543 static int resultRemat (iCode *ic)
2544 {
2545   //    DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2546   if (SKIP_IC(ic) || ic->op == IFX)
2547     return 0;
2548
2549   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2550     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2551     if (sym->remat && !POINTER_SET(ic)) 
2552       return 1;
2553   }
2554
2555   return 0;
2556 }
2557
2558 #if defined(__BORLANDC__) || defined(_MSC_VER)
2559 #define STRCASECMP stricmp
2560 #else
2561 #define STRCASECMP strcasecmp
2562 #endif
2563
2564 #if 0
2565 /*-----------------------------------------------------------------*/
2566 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2567 /*-----------------------------------------------------------------*/
2568 static bool inExcludeList(char *s)
2569 {
2570   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2571     int i =0;
2572     
2573     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2574     if (options.excludeRegs[i] &&
2575     STRCASECMP(options.excludeRegs[i],"none") == 0)
2576         return FALSE ;
2577
2578     for ( i = 0 ; options.excludeRegs[i]; i++) {
2579         if (options.excludeRegs[i] &&
2580         STRCASECMP(s,options.excludeRegs[i]) == 0)
2581             return TRUE;
2582     }
2583     return FALSE ;
2584 }
2585 #endif
2586
2587 /*-----------------------------------------------------------------*/
2588 /* genFunction - generated code for function entry                 */
2589 /*-----------------------------------------------------------------*/
2590 static void genFunction (iCode *ic)
2591 {
2592     symbol *sym;
2593     sym_link *ftype;
2594
2595     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2596
2597     labelOffset += (max_key+4);
2598     max_key=0;
2599     GpsuedoStkPtr=0;
2600     _G.nRegsSaved = 0;
2601     /* create the function header */
2602     pic14_emitcode(";","-----------------------------------------");
2603     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2604     pic14_emitcode(";","-----------------------------------------");
2605
2606     pic14_emitcode("","%s:",sym->rname);
2607     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2608
2609     ftype = operandType(IC_LEFT(ic));
2610
2611     /* if critical function then turn interrupts off */
2612     if (IFFUNC_ISCRITICAL(ftype))
2613         pic14_emitcode("clr","ea");
2614
2615     /* here we need to generate the equates for the
2616        register bank if required */
2617 #if 0
2618     if (FUNC_REGBANK(ftype) != rbank) {
2619         int i ;
2620
2621         rbank = FUNC_REGBANK(ftype);
2622         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2623             if (strcmp(regspic14[i].base,"0") == 0)
2624                 pic14_emitcode("","%s = 0x%02x",
2625                          regspic14[i].dname,
2626                          8*rbank+regspic14[i].offset);
2627             else
2628                 pic14_emitcode ("","%s = %s + 0x%02x",
2629                           regspic14[i].dname,
2630                           regspic14[i].base,
2631                           8*rbank+regspic14[i].offset);
2632         }
2633     }
2634 #endif
2635
2636     /* if this is an interrupt service routine */
2637     if (IFFUNC_ISISR(sym->type)) {
2638 /*  already done in pic14createInterruptVect() - delete me
2639       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2640       emitpcodeNULLop(POC_NOP);
2641       emitpcodeNULLop(POC_NOP);
2642       emitpcodeNULLop(POC_NOP);
2643 */
2644       emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2645       emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2646       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2647       emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2648       emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2649       emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2650       emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2651
2652       pBlockConvert2ISR(pb);
2653 #if 0  
2654         if (!inExcludeList("acc"))          
2655             pic14_emitcode ("push","acc");      
2656         if (!inExcludeList("b"))
2657             pic14_emitcode ("push","b");
2658         if (!inExcludeList("dpl"))
2659             pic14_emitcode ("push","dpl");
2660         if (!inExcludeList("dph"))
2661             pic14_emitcode ("push","dph");
2662         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2663         {
2664             pic14_emitcode ("push", "dpx");
2665             /* Make sure we're using standard DPTR */
2666             pic14_emitcode ("push", "dps");
2667             pic14_emitcode ("mov", "dps, #0x00");
2668             if (options.stack10bit)
2669             {   
2670                 /* This ISR could conceivably use DPTR2. Better save it. */
2671                 pic14_emitcode ("push", "dpl1");
2672                 pic14_emitcode ("push", "dph1");
2673                 pic14_emitcode ("push", "dpx1");
2674             }
2675         }
2676         /* if this isr has no bank i.e. is going to
2677            run with bank 0 , then we need to save more
2678            registers :-) */
2679         if (!FUNC_REGBANK(sym->type)) {
2680
2681             /* if this function does not call any other
2682                function then we can be economical and
2683                save only those registers that are used */
2684             if (! IFFUNC_HASFCALL(sym->type)) {
2685                 int i;
2686
2687                 /* if any registers used */
2688                 if (sym->regsUsed) {
2689                     /* save the registers used */
2690                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2691                         if (bitVectBitValue(sym->regsUsed,i) ||
2692                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2693                           pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);                         
2694                     }
2695                 }
2696                 
2697             } else {
2698                 /* this function has  a function call cannot
2699                    determines register usage so we will have the
2700                    entire bank */
2701                 saverbank(0,ic,FALSE);
2702             }       
2703         }
2704 #endif
2705     } else {
2706         /* if callee-save to be used for this function
2707            then save the registers being used in this function */
2708         if (IFFUNC_CALLEESAVES(sym->type)) {
2709             int i;
2710             
2711             /* if any registers used */
2712             if (sym->regsUsed) {
2713                 /* save the registers used */
2714                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2715                     if (bitVectBitValue(sym->regsUsed,i) ||
2716                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2717                       //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2718                         _G.nRegsSaved++;
2719                     }
2720                 }
2721             }
2722         }
2723     }
2724
2725     /* set the register bank to the desired value */
2726     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2727         pic14_emitcode("push","psw");
2728         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2729     }
2730
2731     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2732
2733         if (options.useXstack) {
2734             pic14_emitcode("mov","r0,%s",spname);
2735             pic14_emitcode("mov","a,_bp");
2736             pic14_emitcode("movx","@r0,a");
2737             pic14_emitcode("inc","%s",spname);
2738         }
2739         else
2740         {
2741             /* set up the stack */
2742             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2743         }
2744         pic14_emitcode ("mov","_bp,%s",spname);
2745     }
2746
2747     /* adjust the stack for the function */
2748     if (sym->stack) {
2749
2750         int i = sym->stack;
2751         if (i > 256 ) 
2752             werror(W_STACK_OVERFLOW,sym->name);
2753
2754         if (i > 3 && sym->recvSize < 4) {              
2755
2756             pic14_emitcode ("mov","a,sp");
2757             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2758             pic14_emitcode ("mov","sp,a");
2759            
2760         }
2761         else
2762             while(i--)
2763                 pic14_emitcode("inc","sp");
2764     }
2765
2766      if (sym->xstack) {
2767
2768         pic14_emitcode ("mov","a,_spx");
2769         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2770         pic14_emitcode ("mov","_spx,a");
2771     }    
2772
2773 }
2774
2775 /*-----------------------------------------------------------------*/
2776 /* genEndFunction - generates epilogue for functions               */
2777 /*-----------------------------------------------------------------*/
2778 static void genEndFunction (iCode *ic)
2779 {
2780     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2781
2782     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2783
2784     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2785     {
2786         pic14_emitcode ("mov","%s,_bp",spname);
2787     }
2788
2789     /* if use external stack but some variables were
2790     added to the local stack then decrement the
2791     local stack */
2792     if (options.useXstack && sym->stack) {      
2793         pic14_emitcode("mov","a,sp");
2794         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2795         pic14_emitcode("mov","sp,a");
2796     }
2797
2798
2799     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2800         if (options.useXstack) {
2801             pic14_emitcode("mov","r0,%s",spname);
2802             pic14_emitcode("movx","a,@r0");
2803             pic14_emitcode("mov","_bp,a");
2804             pic14_emitcode("dec","%s",spname);
2805         }
2806         else
2807         {
2808             pic14_emitcode ("pop","_bp");
2809         }
2810     }
2811
2812     /* restore the register bank  */    
2813     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2814         pic14_emitcode ("pop","psw");
2815
2816     if (IFFUNC_ISISR(sym->type)) {
2817
2818         /* now we need to restore the registers */
2819         /* if this isr has no bank i.e. is going to
2820            run with bank 0 , then we need to save more
2821            registers :-) */
2822         if (!FUNC_REGBANK(sym->type)) {
2823             
2824             /* if this function does not call any other
2825                function then we can be economical and
2826                save only those registers that are used */
2827             if (! IFFUNC_HASFCALL(sym->type)) {
2828                 int i;
2829                 
2830                 /* if any registers used */
2831                 if (sym->regsUsed) {
2832                     /* save the registers used */
2833                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2834                         if (bitVectBitValue(sym->regsUsed,i) ||
2835                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2836                           pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2837                     }
2838                 }
2839                 
2840             } else {
2841                 /* this function has  a function call cannot
2842                    determines register usage so we will have the
2843                    entire bank */
2844                 unsaverbank(0,ic,FALSE);
2845             }       
2846         }
2847 #if 0
2848         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2849         {
2850             if (options.stack10bit)
2851             {
2852                 pic14_emitcode ("pop", "dpx1");
2853                 pic14_emitcode ("pop", "dph1");
2854                 pic14_emitcode ("pop", "dpl1");
2855             }   
2856             pic14_emitcode ("pop", "dps");
2857             pic14_emitcode ("pop", "dpx");
2858         }
2859         if (!inExcludeList("dph"))
2860             pic14_emitcode ("pop","dph");
2861         if (!inExcludeList("dpl"))
2862             pic14_emitcode ("pop","dpl");
2863         if (!inExcludeList("b"))
2864             pic14_emitcode ("pop","b");
2865         if (!inExcludeList("acc"))
2866             pic14_emitcode ("pop","acc");
2867
2868         if (IFFUNC_ISCRITICAL(sym->type))
2869             pic14_emitcode("setb","ea");
2870 #endif
2871
2872         /* if debug then send end of function */
2873 /*      if (options.debug && currFunc) { */
2874         if (currFunc) {
2875             _G.debugLine = 1;
2876             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2877                      FileBaseName(ic->filename),currFunc->lastLine,
2878                      ic->level,ic->block); 
2879             if (IS_STATIC(currFunc->etype))         
2880                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2881             else
2882                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2883             _G.debugLine = 0;
2884         }
2885
2886         pic14_emitcode ("reti","");
2887         emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2888         emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2889         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2890         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2891         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2892         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2893         emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2894         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2895         emitpcodeNULLop(POC_RETFIE);
2896     }
2897     else {
2898         if (IFFUNC_ISCRITICAL(sym->type))
2899             pic14_emitcode("setb","ea");
2900         
2901         if (IFFUNC_CALLEESAVES(sym->type)) {
2902             int i;
2903             
2904             /* if any registers used */
2905             if (sym->regsUsed) {
2906                 /* save the registers used */
2907                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2908                     if (bitVectBitValue(sym->regsUsed,i) ||
2909                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2910                       pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2911                 }
2912             }
2913             
2914         }
2915
2916         /* if debug then send end of function */
2917         if (currFunc) {
2918             _G.debugLine = 1;
2919             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2920                      FileBaseName(ic->filename),currFunc->lastLine,
2921                      ic->level,ic->block); 
2922             if (IS_STATIC(currFunc->etype))         
2923                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2924             else
2925                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2926             _G.debugLine = 0;
2927         }
2928
2929         pic14_emitcode ("return","");
2930         emitpcodeNULLop(POC_RETURN);
2931
2932         /* Mark the end of a function */
2933         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
2934     }
2935
2936 }
2937
2938 /*-----------------------------------------------------------------*/
2939 /* genRet - generate code for return statement                     */
2940 /*-----------------------------------------------------------------*/
2941 static void genRet (iCode *ic)
2942 {
2943   int size,offset = 0 , pushed = 0;
2944     
2945   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2946   /* if we have no return value then
2947      just generate the "ret" */
2948   if (!IC_LEFT(ic)) 
2949     goto jumpret;       
2950     
2951   /* we have something to return then
2952      move the return value into place */
2953   aopOp(IC_LEFT(ic),ic,FALSE);
2954   size = AOP_SIZE(IC_LEFT(ic));
2955     
2956   while (size--) {
2957     char *l ;
2958     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2959       /* #NOCHANGE */
2960       l = aopGet(AOP(IC_LEFT(ic)),offset++,
2961                  FALSE,TRUE);
2962       pic14_emitcode("push","%s",l);
2963       pushed++;
2964     } else {
2965       l = aopGet(AOP(IC_LEFT(ic)),offset,
2966                  FALSE,FALSE);
2967       if (strcmp(fReturn[offset],l)) {
2968       if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
2969            AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
2970           ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2971           ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2972           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2973         }else {
2974           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2975         }
2976         if(size) {
2977           emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
2978         }
2979         offset++;
2980       }
2981     }
2982   }    
2983
2984   if (pushed) {
2985     while(pushed) {
2986       pushed--;
2987       if (strcmp(fReturn[pushed],"a"))
2988         pic14_emitcode("pop",fReturn[pushed]);
2989       else
2990         pic14_emitcode("pop","acc");
2991     }
2992   }
2993   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2994     
2995  jumpret:
2996   /* generate a jump to the return label
2997      if the next is not the return statement */
2998   if (!(ic->next && ic->next->op == LABEL &&
2999         IC_LABEL(ic->next) == returnLabel)) {
3000         
3001     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3002     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3003   }
3004     
3005 }
3006
3007 /*-----------------------------------------------------------------*/
3008 /* genLabel - generates a label                                    */
3009 /*-----------------------------------------------------------------*/
3010 static void genLabel (iCode *ic)
3011 {
3012     /* special case never generate */
3013     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3014     if (IC_LABEL(ic) == entryLabel)
3015         return ;
3016
3017     emitpLabel(IC_LABEL(ic)->key);
3018     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3019 }
3020
3021 /*-----------------------------------------------------------------*/
3022 /* genGoto - generates a goto                                      */
3023 /*-----------------------------------------------------------------*/
3024 //tsd
3025 static void genGoto (iCode *ic)
3026 {
3027   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3028   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3029 }
3030
3031
3032 /*-----------------------------------------------------------------*/
3033 /* genMultbits :- multiplication of bits                           */
3034 /*-----------------------------------------------------------------*/
3035 static void genMultbits (operand *left, 
3036                          operand *right, 
3037                          operand *result)
3038 {
3039   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3040
3041   if(!pic14_sameRegs(AOP(result),AOP(right)))
3042     emitpcode(POC_BSF,  popGet(AOP(result),0));
3043
3044   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3045   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3046   emitpcode(POC_BCF,  popGet(AOP(result),0));
3047
3048 }
3049
3050
3051 /*-----------------------------------------------------------------*/
3052 /* genMultOneByte : 8 bit multiplication & division                */
3053 /*-----------------------------------------------------------------*/
3054 static void genMultOneByte (operand *left,
3055                             operand *right,
3056                             operand *result)
3057 {
3058   sym_link *opetype = operandType(result);
3059
3060   // symbol *lbl ;
3061   int size,offset;
3062
3063   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3064   DEBUGpic14_AopType(__LINE__,left,right,result);
3065   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3066
3067   /* (if two literals, the value is computed before) */
3068   /* if one literal, literal on the right */
3069   if (AOP_TYPE(left) == AOP_LIT){
3070     operand *t = right;
3071     right = left;
3072     left = t;
3073   }
3074
3075   size = AOP_SIZE(result);
3076   if(size == 1) {
3077
3078     if (AOP_TYPE(right) == AOP_LIT){
3079       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3080                      aopGet(AOP(right),0,FALSE,FALSE), 
3081                      aopGet(AOP(left),0,FALSE,FALSE), 
3082                      aopGet(AOP(result),0,FALSE,FALSE));
3083       pic14_emitcode("call","genMultLit");
3084     } else {
3085       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3086                      aopGet(AOP(right),0,FALSE,FALSE), 
3087                      aopGet(AOP(left),0,FALSE,FALSE), 
3088                      aopGet(AOP(result),0,FALSE,FALSE));
3089       pic14_emitcode("call","genMult8X8_8");
3090
3091     }
3092     genMult8X8_8 (left, right,result);
3093
3094
3095     /* signed or unsigned */
3096     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3097     //l = aopGet(AOP(left),0,FALSE,FALSE);
3098     //MOVA(l);       
3099     //pic14_emitcode("mul","ab");
3100     /* if result size = 1, mul signed = mul unsigned */
3101     //aopPut(AOP(result),"a",0);
3102
3103   } else {  // (size > 1)
3104
3105     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3106                    aopGet(AOP(right),0,FALSE,FALSE), 
3107                    aopGet(AOP(left),0,FALSE,FALSE), 
3108                    aopGet(AOP(result),0,FALSE,FALSE));
3109
3110     if (SPEC_USIGN(opetype)){
3111       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3112       genUMult8X8_16 (left, right, result, NULL);
3113
3114       if (size > 2) {
3115         /* for filling the MSBs */
3116         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3117         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3118       }
3119     }
3120     else{
3121       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3122
3123       pic14_emitcode("mov","a,b");
3124
3125       /* adjust the MSB if left or right neg */
3126
3127       /* if one literal */
3128       if (AOP_TYPE(right) == AOP_LIT){
3129         pic14_emitcode("multiply ","right is a lit");
3130         /* AND literal negative */
3131         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3132           /* adjust MSB (c==0 after mul) */
3133           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3134         }
3135       }
3136       else{
3137         genSMult8X8_16 (left, right, result, NULL);
3138       }
3139
3140       if(size > 2){
3141         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3142         /* get the sign */
3143         pic14_emitcode("rlc","a");
3144         pic14_emitcode("subb","a,acc");
3145       }
3146     }
3147
3148     size -= 2;   
3149     offset = 2;
3150     if (size > 0)
3151       while (size--)
3152         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3153     //aopPut(AOP(result),"a",offset++);
3154   }
3155 }
3156
3157 /*-----------------------------------------------------------------*/
3158 /* genMult - generates code for multiplication                     */
3159 /*-----------------------------------------------------------------*/
3160 static void genMult (iCode *ic)
3161 {
3162     operand *left = IC_LEFT(ic);
3163     operand *right = IC_RIGHT(ic);
3164     operand *result= IC_RESULT(ic);   
3165
3166     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3167     /* assign the amsops */
3168     aopOp (left,ic,FALSE);
3169     aopOp (right,ic,FALSE);
3170     aopOp (result,ic,TRUE);
3171
3172   DEBUGpic14_AopType(__LINE__,left,right,result);
3173
3174     /* special cases first */
3175     /* both are bits */
3176     if (AOP_TYPE(left) == AOP_CRY &&
3177         AOP_TYPE(right)== AOP_CRY) {
3178         genMultbits(left,right,result);
3179         goto release ;
3180     }
3181
3182     /* if both are of size == 1 */
3183     if (AOP_SIZE(left) == 1 &&
3184         AOP_SIZE(right) == 1 ) {
3185         genMultOneByte(left,right,result);
3186         goto release ;
3187     }
3188
3189     pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3190
3191     /* should have been converted to function call */
3192     //assert(0) ;
3193
3194 release :
3195     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3196     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3197     freeAsmop(result,NULL,ic,TRUE); 
3198 }
3199
3200 /*-----------------------------------------------------------------*/
3201 /* genDivbits :- division of bits                                  */
3202 /*-----------------------------------------------------------------*/
3203 static void genDivbits (operand *left, 
3204                         operand *right, 
3205                         operand *result)
3206 {
3207
3208     char *l;
3209
3210     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3211     /* the result must be bit */    
3212     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3213     l = aopGet(AOP(left),0,FALSE,FALSE);
3214
3215     MOVA(l);    
3216
3217     pic14_emitcode("div","ab");
3218     pic14_emitcode("rrc","a");
3219     aopPut(AOP(result),"c",0);
3220 }
3221
3222 /*-----------------------------------------------------------------*/
3223 /* genDivOneByte : 8 bit division                                  */
3224 /*-----------------------------------------------------------------*/
3225 static void genDivOneByte (operand *left,
3226                            operand *right,
3227                            operand *result)
3228 {
3229     sym_link *opetype = operandType(result);
3230     char *l ;
3231     symbol *lbl ;
3232     int size,offset;
3233
3234     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3235     size = AOP_SIZE(result) - 1;
3236     offset = 1;
3237     /* signed or unsigned */
3238     if (SPEC_USIGN(opetype)) {
3239         /* unsigned is easy */
3240         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3241         l = aopGet(AOP(left),0,FALSE,FALSE);
3242         MOVA(l);        
3243         pic14_emitcode("div","ab");
3244         aopPut(AOP(result),"a",0);
3245         while (size--)
3246             aopPut(AOP(result),zero,offset++);
3247         return ;
3248     }
3249
3250     /* signed is a little bit more difficult */
3251
3252     /* save the signs of the operands */
3253     l = aopGet(AOP(left),0,FALSE,FALSE);    
3254     MOVA(l);    
3255     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3256     pic14_emitcode("push","acc"); /* save it on the stack */
3257
3258     /* now sign adjust for both left & right */
3259     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3260     MOVA(l);       
3261     lbl = newiTempLabel(NULL);
3262     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3263     pic14_emitcode("cpl","a");   
3264     pic14_emitcode("inc","a");
3265     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3266     pic14_emitcode("mov","b,a");
3267
3268     /* sign adjust left side */
3269     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3270     MOVA(l);
3271
3272     lbl = newiTempLabel(NULL);
3273     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3274     pic14_emitcode("cpl","a");
3275     pic14_emitcode("inc","a");
3276     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3277
3278     /* now the division */
3279     pic14_emitcode("div","ab");
3280     /* we are interested in the lower order
3281     only */
3282     pic14_emitcode("mov","b,a");
3283     lbl = newiTempLabel(NULL);
3284     pic14_emitcode("pop","acc");   
3285     /* if there was an over flow we don't 
3286     adjust the sign of the result */
3287     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3288     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3289     CLRC;
3290     pic14_emitcode("clr","a");
3291     pic14_emitcode("subb","a,b");
3292     pic14_emitcode("mov","b,a");
3293     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3294
3295     /* now we are done */
3296     aopPut(AOP(result),"b",0);
3297     if(size > 0){
3298         pic14_emitcode("mov","c,b.7");
3299         pic14_emitcode("subb","a,acc");   
3300     }
3301     while (size--)
3302         aopPut(AOP(result),"a",offset++);
3303
3304 }
3305
3306 /*-----------------------------------------------------------------*/
3307 /* genDiv - generates code for division                            */
3308 /*-----------------------------------------------------------------*/
3309 static void genDiv (iCode *ic)
3310 {
3311     operand *left = IC_LEFT(ic);
3312     operand *right = IC_RIGHT(ic);
3313     operand *result= IC_RESULT(ic);   
3314
3315     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3316     /* assign the amsops */
3317     aopOp (left,ic,FALSE);
3318     aopOp (right,ic,FALSE);
3319     aopOp (result,ic,TRUE);
3320
3321     /* special cases first */
3322     /* both are bits */
3323     if (AOP_TYPE(left) == AOP_CRY &&
3324         AOP_TYPE(right)== AOP_CRY) {
3325         genDivbits(left,right,result);
3326         goto release ;
3327     }
3328
3329     /* if both are of size == 1 */
3330     if (AOP_SIZE(left) == 1 &&
3331         AOP_SIZE(right) == 1 ) {
3332         genDivOneByte(left,right,result);
3333         goto release ;
3334     }
3335
3336     /* should have been converted to function call */
3337     assert(0);
3338 release :
3339     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3340     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3341     freeAsmop(result,NULL,ic,TRUE); 
3342 }
3343
3344 /*-----------------------------------------------------------------*/
3345 /* genModbits :- modulus of bits                                   */
3346 /*-----------------------------------------------------------------*/
3347 static void genModbits (operand *left, 
3348                         operand *right, 
3349                         operand *result)
3350 {
3351
3352     char *l;
3353
3354     /* the result must be bit */    
3355     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3356     l = aopGet(AOP(left),0,FALSE,FALSE);
3357
3358     MOVA(l);       
3359
3360     pic14_emitcode("div","ab");
3361     pic14_emitcode("mov","a,b");
3362     pic14_emitcode("rrc","a");
3363     aopPut(AOP(result),"c",0);
3364 }
3365
3366 /*-----------------------------------------------------------------*/
3367 /* genModOneByte : 8 bit modulus                                   */
3368 /*-----------------------------------------------------------------*/
3369 static void genModOneByte (operand *left,
3370                            operand *right,
3371                            operand *result)
3372 {
3373     sym_link *opetype = operandType(result);
3374     char *l ;
3375     symbol *lbl ;
3376
3377     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3378     /* signed or unsigned */
3379     if (SPEC_USIGN(opetype)) {
3380         /* unsigned is easy */
3381         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3382         l = aopGet(AOP(left),0,FALSE,FALSE);
3383         MOVA(l);    
3384         pic14_emitcode("div","ab");
3385         aopPut(AOP(result),"b",0);
3386         return ;
3387     }
3388
3389     /* signed is a little bit more difficult */
3390
3391     /* save the signs of the operands */
3392     l = aopGet(AOP(left),0,FALSE,FALSE);    
3393     MOVA(l);
3394
3395     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3396     pic14_emitcode("push","acc"); /* save it on the stack */
3397
3398     /* now sign adjust for both left & right */
3399     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3400     MOVA(l);
3401
3402     lbl = newiTempLabel(NULL);
3403     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3404     pic14_emitcode("cpl","a");   
3405     pic14_emitcode("inc","a");
3406     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3407     pic14_emitcode("mov","b,a"); 
3408
3409     /* sign adjust left side */
3410     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3411     MOVA(l);
3412
3413     lbl = newiTempLabel(NULL);
3414     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3415     pic14_emitcode("cpl","a");   
3416     pic14_emitcode("inc","a");
3417     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3418
3419     /* now the multiplication */
3420     pic14_emitcode("div","ab");
3421     /* we are interested in the lower order
3422     only */
3423     lbl = newiTempLabel(NULL);
3424     pic14_emitcode("pop","acc");   
3425     /* if there was an over flow we don't 
3426     adjust the sign of the result */
3427     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3428     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3429     CLRC ;
3430     pic14_emitcode("clr","a");
3431     pic14_emitcode("subb","a,b");
3432     pic14_emitcode("mov","b,a");
3433     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3434
3435     /* now we are done */
3436     aopPut(AOP(result),"b",0);
3437
3438 }
3439
3440 /*-----------------------------------------------------------------*/
3441 /* genMod - generates code for division                            */
3442 /*-----------------------------------------------------------------*/
3443 static void genMod (iCode *ic)
3444 {
3445     operand *left = IC_LEFT(ic);
3446     operand *right = IC_RIGHT(ic);
3447     operand *result= IC_RESULT(ic);  
3448
3449     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3450     /* assign the amsops */
3451     aopOp (left,ic,FALSE);
3452     aopOp (right,ic,FALSE);
3453     aopOp (result,ic,TRUE);
3454
3455     /* special cases first */
3456     /* both are bits */
3457     if (AOP_TYPE(left) == AOP_CRY &&
3458         AOP_TYPE(right)== AOP_CRY) {
3459         genModbits(left,right,result);
3460         goto release ;
3461     }
3462
3463     /* if both are of size == 1 */
3464     if (AOP_SIZE(left) == 1 &&
3465         AOP_SIZE(right) == 1 ) {
3466         genModOneByte(left,right,result);
3467         goto release ;
3468     }
3469
3470     /* should have been converted to function call */
3471     assert(0);
3472
3473 release :
3474     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3475     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3476     freeAsmop(result,NULL,ic,TRUE); 
3477 }
3478
3479 /*-----------------------------------------------------------------*/
3480 /* genIfxJump :- will create a jump depending on the ifx           */
3481 /*-----------------------------------------------------------------*/
3482 /*
3483   note: May need to add parameter to indicate when a variable is in bit space.
3484 */
3485 static void genIfxJump (iCode *ic, char *jval)
3486 {
3487
3488     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3489     /* if true label then we jump if condition
3490     supplied is true */
3491     if ( IC_TRUE(ic) ) {
3492
3493         if(strcmp(jval,"a") == 0)
3494           emitSKPZ;
3495         else if (strcmp(jval,"c") == 0)
3496           emitSKPC;
3497         else {
3498           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3499           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3500         }
3501
3502         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3503         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3504
3505     }
3506     else {
3507         /* false label is present */
3508         if(strcmp(jval,"a") == 0)
3509           emitSKPNZ;
3510         else if (strcmp(jval,"c") == 0)
3511           emitSKPNC;
3512         else {
3513           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3514           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3515         }
3516
3517         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3518         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3519
3520     }
3521
3522
3523     /* mark the icode as generated */
3524     ic->generated = 1;
3525 }
3526
3527 /*-----------------------------------------------------------------*/
3528 /* genSkip                                                         */
3529 /*-----------------------------------------------------------------*/
3530 static void genSkip(iCode *ifx,int status_bit)
3531 {
3532   if(!ifx)
3533     return;
3534
3535   if ( IC_TRUE(ifx) ) {
3536     switch(status_bit) {
3537     case 'z':
3538       emitSKPNZ;
3539       break;
3540
3541     case 'c':
3542       emitSKPNC;
3543       break;
3544
3545     case 'd':
3546       emitSKPDC;
3547       break;
3548
3549     }
3550
3551     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3552     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3553
3554   } else {
3555
3556     switch(status_bit) {
3557
3558     case 'z':
3559       emitSKPZ;
3560       break;
3561
3562     case 'c':
3563       emitSKPC;
3564       break;
3565
3566     case 'd':
3567       emitSKPDC;
3568       break;
3569     }
3570     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3571     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3572
3573   }
3574
3575 }
3576
3577 /*-----------------------------------------------------------------*/
3578 /* genSkipc                                                        */
3579 /*-----------------------------------------------------------------*/
3580 static void genSkipc(resolvedIfx *rifx)
3581 {
3582   if(!rifx)
3583     return;
3584
3585   if(rifx->condition)
3586     emitSKPC;
3587   else
3588     emitSKPNC;
3589
3590   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3591   rifx->generated = 1;
3592 }
3593
3594 /*-----------------------------------------------------------------*/
3595 /* genSkipz2                                                       */
3596 /*-----------------------------------------------------------------*/
3597 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3598 {
3599   if(!rifx)
3600     return;
3601
3602   if( (rifx->condition ^ invert_condition) & 1)
3603     emitSKPZ;
3604   else
3605     emitSKPNZ;
3606
3607   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3608   rifx->generated = 1;
3609 }
3610
3611 /*-----------------------------------------------------------------*/
3612 /* genSkipz                                                        */
3613 /*-----------------------------------------------------------------*/
3614 static void genSkipz(iCode *ifx, int condition)
3615 {
3616   if(!ifx)
3617     return;
3618
3619   if(condition)
3620     emitSKPNZ;
3621   else
3622     emitSKPZ;
3623
3624   if ( IC_TRUE(ifx) )
3625     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3626   else
3627     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3628
3629   if ( IC_TRUE(ifx) )
3630     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3631   else
3632     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3633
3634 }
3635 /*-----------------------------------------------------------------*/
3636 /* genSkipCond                                                     */
3637 /*-----------------------------------------------------------------*/
3638 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3639 {
3640   if(!rifx)
3641     return;
3642
3643   if(rifx->condition)
3644     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3645   else
3646     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3647
3648
3649   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3650   rifx->generated = 1;
3651 }
3652
3653 #if 0
3654 /*-----------------------------------------------------------------*/
3655 /* genChkZeroes :- greater or less than comparison                 */
3656 /*     For each byte in a literal that is zero, inclusive or the   */
3657 /*     the corresponding byte in the operand with W                */
3658 /*     returns true if any of the bytes are zero                   */
3659 /*-----------------------------------------------------------------*/
3660 static int genChkZeroes(operand *op, int lit,  int size)
3661 {
3662
3663   int i;
3664   int flag =1;
3665
3666   while(size--) {
3667     i = (lit >> (size*8)) & 0xff;
3668
3669     if(i==0) {
3670       if(flag) 
3671         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3672       else
3673         emitpcode(POC_IORFW, popGet(AOP(op),size));
3674       flag = 0;
3675     }
3676   }
3677
3678   return (flag==0);
3679 }
3680 #endif
3681
3682 /*-----------------------------------------------------------------*/
3683 /* genCmp :- greater or less than comparison                       */
3684 /*-----------------------------------------------------------------*/
3685 static void genCmp (operand *left,operand *right,
3686                     operand *result, iCode *ifx, int sign)
3687 {
3688   int size; //, offset = 0 ;
3689   unsigned long lit = 0L,i = 0;
3690   resolvedIfx rFalseIfx;
3691   //  resolvedIfx rTrueIfx;
3692   symbol *truelbl;
3693   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3694 /*
3695   if(ifx) {
3696     DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3697     DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3698   }
3699 */
3700
3701   resolveIfx(&rFalseIfx,ifx);
3702   truelbl  = newiTempLabel(NULL);
3703   size = max(AOP_SIZE(left),AOP_SIZE(right));
3704
3705   DEBUGpic14_AopType(__LINE__,left,right,result);
3706
3707 #define _swapp
3708
3709   /* if literal is on the right then swap with left */
3710   if ((AOP_TYPE(right) == AOP_LIT)) {
3711     operand *tmp = right ;
3712     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3713     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3714 #ifdef _swapp
3715
3716     lit = (lit - 1) & mask;
3717     right = left;
3718     left = tmp;
3719     rFalseIfx.condition ^= 1;
3720 #endif
3721
3722   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3723     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3724   }
3725
3726
3727   //if(IC_TRUE(ifx) == NULL)
3728   /* if left & right are bit variables */
3729   if (AOP_TYPE(left) == AOP_CRY &&
3730       AOP_TYPE(right) == AOP_CRY ) {
3731     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3732     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3733   } else {
3734     /* subtract right from left if at the
3735        end the carry flag is set then we know that
3736        left is greater than right */
3737
3738     //    {
3739
3740     symbol *lbl  = newiTempLabel(NULL);
3741
3742 #ifndef _swapp
3743     if(AOP_TYPE(right) == AOP_LIT) {
3744
3745       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3746
3747       DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3748
3749       /* special cases */
3750
3751       if(lit == 0) {
3752
3753         if(sign != 0) 
3754           genSkipCond(&rFalseIfx,left,size-1,7);
3755         else 
3756           /* no need to compare to 0...*/
3757           /* NOTE: this is a de-generate compare that most certainly 
3758            *       creates some dead code. */
3759           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3760
3761         if(ifx) ifx->generated = 1;
3762         return;
3763
3764       }
3765       size--;
3766
3767       if(size == 0) {
3768         //i = (lit >> (size*8)) & 0xff;
3769         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3770         
3771         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3772
3773         i = ((0-lit) & 0xff);
3774         if(sign) {
3775           if( i == 0x81) { 
3776             /* lit is 0x7f, all signed chars are less than
3777              * this except for 0x7f itself */
3778             emitpcode(POC_XORLW, popGetLit(0x7f));
3779             genSkipz2(&rFalseIfx,0);
3780           } else {
3781             emitpcode(POC_ADDLW, popGetLit(0x80));
3782             emitpcode(POC_ADDLW, popGetLit(i^0x80));
3783             genSkipc(&rFalseIfx);
3784           }
3785
3786         } else {
3787           if(lit == 1) {
3788             genSkipz2(&rFalseIfx,1);
3789           } else {
3790             emitpcode(POC_ADDLW, popGetLit(i));
3791             genSkipc(&rFalseIfx);
3792           }
3793         }
3794
3795         if(ifx) ifx->generated = 1;
3796         return;
3797       }
3798
3799       /* chars are out of the way. now do ints and longs */
3800
3801
3802       DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3803         
3804       /* special cases */
3805
3806       if(sign) {
3807
3808         if(lit == 0) {
3809           genSkipCond(&rFalseIfx,left,size,7);
3810           if(ifx) ifx->generated = 1;
3811           return;
3812         }
3813
3814         if(lit <0x100) {
3815           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3816
3817           //rFalseIfx.condition ^= 1;
3818           //genSkipCond(&rFalseIfx,left,size,7);
3819           //rFalseIfx.condition ^= 1;
3820
3821           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3822           if(rFalseIfx.condition)
3823             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3824           else
3825             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3826
3827           emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3828           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3829           emitpcode(POC_MOVFW, popGet(AOP(left),1));
3830
3831           while(size > 1)
3832             emitpcode(POC_IORFW, popGet(AOP(left),size--));
3833
3834           if(rFalseIfx.condition) {
3835             emitSKPZ;
3836             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3837
3838           } else {
3839             emitSKPNZ;
3840           }
3841
3842           genSkipc(&rFalseIfx);
3843           emitpLabel(truelbl->key);
3844           if(ifx) ifx->generated = 1;
3845           return;
3846
3847         }
3848
3849         if(size == 1) {
3850
3851           if( (lit & 0xff) == 0) {
3852             /* lower byte is zero */
3853             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3854             i = ((lit >> 8) & 0xff) ^0x80;
3855             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3856             emitpcode(POC_ADDLW, popGetLit( 0x80));
3857             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3858             genSkipc(&rFalseIfx);
3859
3860
3861             if(ifx) ifx->generated = 1;
3862             return;
3863
3864           }
3865         } else {
3866           /* Special cases for signed longs */
3867           if( (lit & 0xffffff) == 0) {
3868             /* lower byte is zero */
3869             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3870             i = ((lit >> 8*3) & 0xff) ^0x80;
3871             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3872             emitpcode(POC_ADDLW, popGetLit( 0x80));
3873             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3874             genSkipc(&rFalseIfx);
3875
3876
3877             if(ifx) ifx->generated = 1;
3878             return;
3879
3880           }
3881
3882         }
3883
3884
3885         if(lit & (0x80 << (size*8))) {
3886           /* lit is negative */
3887           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3888
3889           //genSkipCond(&rFalseIfx,left,size,7);
3890
3891           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3892
3893           if(rFalseIfx.condition)
3894             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3895           else
3896             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3897
3898
3899         } else {
3900           /* lit is positive */
3901           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3902           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3903           if(rFalseIfx.condition)
3904             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3905           else
3906             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3907
3908         }
3909
3910         /* There are no more special cases, so perform a general compare */
3911   
3912         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3913         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3914
3915         while(size--) {
3916
3917           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3918           emitSKPNZ;
3919           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3920         }
3921         //rFalseIfx.condition ^= 1;
3922         genSkipc(&rFalseIfx);
3923
3924         emitpLabel(truelbl->key);
3925
3926         if(ifx) ifx->generated = 1;
3927         return;
3928
3929
3930       }
3931
3932
3933       /* sign is out of the way. So now do an unsigned compare */
3934       DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3935
3936
3937       /* General case - compare to an unsigned literal on the right.*/
3938
3939       i = (lit >> (size*8)) & 0xff;
3940       emitpcode(POC_MOVLW, popGetLit(i));
3941       emitpcode(POC_SUBFW, popGet(AOP(left),size));
3942       while(size--) {
3943         i = (lit >> (size*8)) & 0xff;
3944
3945         if(i) {
3946           emitpcode(POC_MOVLW, popGetLit(i));
3947           emitSKPNZ;
3948           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3949         } else {
3950           /* this byte of the lit is zero, 
3951            *if it's not the last then OR in the variable */
3952           if(size)
3953             emitpcode(POC_IORFW, popGet(AOP(left),size));
3954         }
3955       }
3956
3957
3958       emitpLabel(lbl->key);
3959       //if(emitFinalCheck)
3960       genSkipc(&rFalseIfx);
3961       if(sign)
3962         emitpLabel(truelbl->key);
3963
3964       if(ifx) ifx->generated = 1;
3965       return;
3966
3967
3968     }
3969 #endif  // _swapp
3970
3971     if(AOP_TYPE(left) == AOP_LIT) {
3972       //symbol *lbl = newiTempLabel(NULL);
3973
3974       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3975
3976
3977       DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
3978
3979       /* Special cases */
3980       if((lit == 0) && (sign == 0)){
3981
3982         size--;
3983         emitpcode(POC_MOVFW, popGet(AOP(right),size));
3984         while(size) 
3985           emitpcode(POC_IORFW, popGet(AOP(right),--size));
3986
3987         genSkipz2(&rFalseIfx,0);
3988         if(ifx) ifx->generated = 1;
3989         return;
3990       }
3991
3992       if(size==1) {
3993         /* Special cases */
3994         lit &= 0xff;
3995         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3996           /* degenerate compare can never be true */
3997           if(rFalseIfx.condition == 0)
3998             emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3999
4000           if(ifx) ifx->generated = 1;
4001           return;
4002         }
4003
4004         if(sign) {
4005           /* signed comparisons to a literal byte */
4006
4007           int lp1 = (lit+1) & 0xff;
4008
4009           DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4010           switch (lp1) {
4011           case 0:
4012             rFalseIfx.condition ^= 1;
4013             genSkipCond(&rFalseIfx,right,0,7);
4014             break;
4015           case 0x7f:
4016             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4017             emitpcode(POC_XORLW, popGetLit(0x7f));
4018             genSkipz2(&rFalseIfx,1);
4019             break;
4020           default:
4021             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4022             emitpcode(POC_ADDLW, popGetLit(0x80));
4023             emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4024             rFalseIfx.condition ^= 1;
4025             genSkipc(&rFalseIfx);
4026             break;
4027           }
4028           if(ifx) ifx->generated = 1;
4029         } else {
4030           /* unsigned comparisons to a literal byte */
4031
4032           switch(lit & 0xff ) {
4033           case 0:
4034             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4035             genSkipz2(&rFalseIfx,0);
4036             if(ifx) ifx->generated = 1;
4037             break;
4038           case 0x7f:
4039             rFalseIfx.condition ^= 1;
4040             genSkipCond(&rFalseIfx,right,0,7);
4041             if(ifx) ifx->generated = 1;
4042             break;
4043
4044           default:
4045             emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4046             emitpcode(POC_SUBFW, popGet(AOP(right),0));
4047             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4048             rFalseIfx.condition ^= 1;
4049             if (AOP_TYPE(result) == AOP_CRY) {
4050               genSkipc(&rFalseIfx);
4051               if(ifx) ifx->generated = 1;
4052             } else {
4053               DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4054               emitpcode(POC_CLRF, popGet(AOP(result),0));
4055               emitpcode(POC_RLF, popGet(AOP(result),0));
4056               emitpcode(POC_MOVLW, popGetLit(0x01));
4057               emitpcode(POC_XORWF, popGet(AOP(result),0));
4058             }         
4059             break;
4060           }
4061         }
4062
4063         //goto check_carry;
4064         return;
4065
4066       } else {
4067
4068         /* Size is greater than 1 */
4069
4070         if(sign) {
4071           int lp1 = lit+1;
4072
4073           size--;
4074
4075           if(lp1 == 0) {
4076             /* this means lit = 0xffffffff, or -1 */
4077
4078
4079             DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4080             rFalseIfx.condition ^= 1;
4081             genSkipCond(&rFalseIfx,right,size,7);
4082             if(ifx) ifx->generated = 1;
4083             return;
4084           }
4085
4086           if(lit == 0) {
4087             int s = size;
4088
4089             if(rFalseIfx.condition) {
4090               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4091               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4092             }
4093
4094             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4095             while(size--)
4096               emitpcode(POC_IORFW, popGet(AOP(right),size));
4097
4098
4099             emitSKPZ;
4100             if(rFalseIfx.condition) {
4101               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4102               emitpLabel(truelbl->key);
4103             }else {
4104               rFalseIfx.condition ^= 1;
4105               genSkipCond(&rFalseIfx,right,s,7);
4106             }
4107
4108             if(ifx) ifx->generated = 1;
4109             return;
4110           }
4111
4112           if((size == 1) &&  (0 == (lp1&0xff))) {
4113             /* lower byte of signed word is zero */
4114             DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4115             i = ((lp1 >> 8) & 0xff) ^0x80;
4116             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4117             emitpcode(POC_ADDLW, popGetLit( 0x80));
4118             emitpcode(POC_ADDLW, popGetLit(0x100-i));
4119             rFalseIfx.condition ^= 1;
4120             genSkipc(&rFalseIfx);
4121
4122
4123             if(ifx) ifx->generated = 1;
4124             return;
4125           }
4126
4127           if(lit & (0x80 << (size*8))) {
4128             /* Lit is less than zero */
4129             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4130             //rFalseIfx.condition ^= 1;
4131             //genSkipCond(&rFalseIfx,left,size,7);
4132             //rFalseIfx.condition ^= 1;
4133             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4134             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4135
4136             if(rFalseIfx.condition)
4137               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4138             else
4139               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4140
4141
4142           } else {
4143             /* Lit is greater than or equal to zero */
4144             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4145             //rFalseIfx.condition ^= 1;
4146             //genSkipCond(&rFalseIfx,right,size,7);
4147             //rFalseIfx.condition ^= 1;
4148
4149             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4150             //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4151
4152             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4153             if(rFalseIfx.condition)
4154               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4155             else
4156               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4157
4158           }
4159
4160
4161           emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4162           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4163
4164           while(size--) {
4165
4166             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4167             emitSKPNZ;
4168             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4169           }
4170           rFalseIfx.condition ^= 1;
4171           //rFalseIfx.condition = 1;
4172           genSkipc(&rFalseIfx);
4173
4174           emitpLabel(truelbl->key);
4175
4176           if(ifx) ifx->generated = 1;
4177           return;
4178           // end of if (sign)
4179         } else {
4180
4181           /* compare word or long to an unsigned literal on the right.*/
4182
4183
4184           size--;
4185           if(lit < 0xff) {
4186             DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4187             switch (lit) {
4188             case 0:
4189               break; /* handled above */
4190 /*
4191             case 0xff:
4192               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4193               while(size--)
4194                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4195               genSkipz2(&rFalseIfx,0);
4196               break;
4197 */
4198             default:
4199               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4200               while(--size)
4201                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4202
4203               emitSKPZ;
4204               if(rFalseIfx.condition)
4205                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4206               else
4207                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4208
4209
4210               emitpcode(POC_MOVLW, popGetLit(lit+1));
4211               emitpcode(POC_SUBFW, popGet(AOP(right),0));
4212
4213               rFalseIfx.condition ^= 1;
4214               genSkipc(&rFalseIfx);
4215             }
4216
4217             emitpLabel(truelbl->key);
4218
4219             if(ifx) ifx->generated = 1;
4220             return;
4221           }
4222
4223
4224           lit++;
4225           DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4226           i = (lit >> (size*8)) & 0xff;
4227
4228           emitpcode(POC_MOVLW, popGetLit(i));
4229           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4230
4231           while(size--) {
4232             i = (lit >> (size*8)) & 0xff;
4233
4234             if(i) {
4235               emitpcode(POC_MOVLW, popGetLit(i));
4236               emitSKPNZ;
4237               emitpcode(POC_SUBFW, popGet(AOP(right),size));
4238             } else {
4239               /* this byte of the lit is zero, 
4240                *if it's not the last then OR in the variable */
4241               if(size)
4242                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4243             }
4244           }
4245
4246
4247           emitpLabel(lbl->key);
4248
4249           rFalseIfx.condition ^= 1;
4250           genSkipc(&rFalseIfx);
4251         }
4252
4253         if(sign)
4254           emitpLabel(truelbl->key);
4255         if(ifx) ifx->generated = 1;
4256         return;
4257       }
4258     }
4259     /* Compare two variables */
4260
4261     DEBUGpic14_emitcode(";sign","%d",sign);
4262
4263     size--;
4264     if(sign) {
4265       /* Sigh. thus sucks... */
4266       if(size) {
4267         emitpcode(POC_MOVFW, popGet(AOP(left),size));
4268         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4269         emitpcode(POC_MOVLW, popGetLit(0x80));
4270         emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4271         emitpcode(POC_XORFW, popGet(AOP(right),size));
4272         emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4273       } else {
4274         /* Signed char comparison */
4275         /* Special thanks to Nikolai Golovchenko for this snippet */
4276         emitpcode(POC_MOVFW, popGet(AOP(right),0));
4277         emitpcode(POC_SUBFW, popGet(AOP(left),0));
4278         emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4279         emitpcode(POC_XORFW, popGet(AOP(left),0));
4280         emitpcode(POC_XORFW, popGet(AOP(right),0));
4281         emitpcode(POC_ADDLW, popGetLit(0x80));
4282
4283         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4284         genSkipc(&rFalseIfx);
4285           
4286         if(ifx) ifx->generated = 1;
4287         return;
4288       }
4289
4290     } else {
4291
4292       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4293       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4294     }
4295
4296
4297     /* The rest of the bytes of a multi-byte compare */
4298     while (size) {
4299
4300       emitSKPZ;
4301       emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4302       size--;
4303
4304       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4305       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4306
4307
4308     }
4309
4310     emitpLabel(lbl->key);
4311
4312     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4313     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4314         (AOP_TYPE(result) == AOP_REG)) {
4315       emitpcode(POC_CLRF, popGet(AOP(result),0));
4316       emitpcode(POC_RLF, popGet(AOP(result),0));
4317     } else {
4318       genSkipc(&rFalseIfx);
4319     }         
4320     //genSkipc(&rFalseIfx);
4321     if(ifx) ifx->generated = 1;
4322
4323     return;
4324
4325   }
4326
4327   // check_carry:
4328   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4329     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4330     pic14_outBitC(result);
4331   } else {
4332     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4333     /* if the result is used in the next
4334        ifx conditional branch then generate
4335        code a little differently */
4336     if (ifx )
4337       genIfxJump (ifx,"c");
4338     else
4339       pic14_outBitC(result);
4340     /* leave the result in acc */
4341   }
4342
4343 }
4344
4345 /*-----------------------------------------------------------------*/
4346 /* genCmpGt :- greater than comparison                             */
4347 /*-----------------------------------------------------------------*/
4348 static void genCmpGt (iCode *ic, iCode *ifx)
4349 {
4350     operand *left, *right, *result;
4351     sym_link *letype , *retype;
4352     int sign ;
4353
4354     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4355     left = IC_LEFT(ic);
4356     right= IC_RIGHT(ic);
4357     result = IC_RESULT(ic);
4358
4359     letype = getSpec(operandType(left));
4360     retype =getSpec(operandType(right));
4361     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4362     /* assign the amsops */
4363     aopOp (left,ic,FALSE);
4364     aopOp (right,ic,FALSE);
4365     aopOp (result,ic,TRUE);
4366
4367     genCmp(right, left, result, ifx, sign);
4368
4369     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4370     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4371     freeAsmop(result,NULL,ic,TRUE); 
4372 }
4373
4374 /*-----------------------------------------------------------------*/
4375 /* genCmpLt - less than comparisons                                */
4376 /*-----------------------------------------------------------------*/
4377 static void genCmpLt (iCode *ic, iCode *ifx)
4378 {
4379     operand *left, *right, *result;
4380     sym_link *letype , *retype;
4381     int sign ;
4382
4383     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4384     left = IC_LEFT(ic);
4385     right= IC_RIGHT(ic);
4386     result = IC_RESULT(ic);
4387
4388     letype = getSpec(operandType(left));
4389     retype =getSpec(operandType(right));
4390     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4391
4392     /* assign the amsops */
4393     aopOp (left,ic,FALSE);
4394     aopOp (right,ic,FALSE);
4395     aopOp (result,ic,TRUE);
4396
4397     genCmp(left, right, result, ifx, sign);
4398
4399     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4400     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4401     freeAsmop(result,NULL,ic,TRUE); 
4402 }
4403
4404 /*-----------------------------------------------------------------*/
4405 /* genc16bit2lit - compare a 16 bit value to a literal             */
4406 /*-----------------------------------------------------------------*/
4407 static void genc16bit2lit(operand *op, int lit, int offset)
4408 {
4409   int i;
4410
4411   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4412   if( (lit&0xff) == 0) 
4413     i=1;
4414   else
4415     i=0;
4416
4417   switch( BYTEofLONG(lit,i)) { 
4418   case 0:
4419     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4420     break;
4421   case 1:
4422     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4423     break;
4424   case 0xff:
4425     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4426     break;
4427   default:
4428     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4429     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4430   }
4431
4432   i ^= 1;
4433
4434   switch( BYTEofLONG(lit,i)) { 
4435   case 0:
4436     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4437     break;
4438   case 1:
4439     emitSKPNZ;
4440     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4441     break;
4442   case 0xff:
4443     emitSKPNZ;
4444     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4445     break;
4446   default:
4447     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4448     emitSKPNZ;
4449     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4450
4451   }
4452
4453 }
4454
4455 /*-----------------------------------------------------------------*/
4456 /* gencjneshort - compare and jump if not equal                    */
4457 /*-----------------------------------------------------------------*/
4458 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4459 {
4460   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4461   int offset = 0;
4462   int res_offset = 0;  /* the result may be a different size then left or right */
4463   int res_size = AOP_SIZE(result);
4464   resolvedIfx rIfx;
4465   symbol *lbl;
4466
4467   unsigned long lit = 0L;
4468   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4469   DEBUGpic14_AopType(__LINE__,left,right,result);
4470   if(result)
4471     DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4472   resolveIfx(&rIfx,ifx);
4473   lbl =  newiTempLabel(NULL);
4474
4475
4476   /* if the left side is a literal or 
4477      if the right is in a pointer register and left 
4478      is not */
4479   if ((AOP_TYPE(left) == AOP_LIT) || 
4480       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4481     operand *t = right;
4482     right = left;
4483     left = t;
4484   }
4485   if(AOP_TYPE(right) == AOP_LIT)
4486     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4487
4488   /* if the right side is a literal then anything goes */
4489   if (AOP_TYPE(right) == AOP_LIT &&
4490       AOP_TYPE(left) != AOP_DIR ) {
4491     switch(size) {
4492     case 2:
4493       genc16bit2lit(left, lit, 0);
4494       emitSKPNZ;
4495       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4496       break;
4497     default:
4498       while (size--) {
4499         if(lit & 0xff) {
4500           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4501           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4502         } else {
4503           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4504         }
4505
4506         emitSKPNZ;
4507         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4508         offset++;
4509         if(res_offset < res_size-1)
4510           res_offset++;
4511         lit >>= 8;
4512       }
4513       break;
4514     }
4515   }
4516
4517   /* if the right side is in a register or in direct space or
4518      if the left is a pointer register & right is not */    
4519   else if (AOP_TYPE(right) == AOP_REG ||
4520            AOP_TYPE(right) == AOP_DIR || 
4521            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4522            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4523     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4524     int lbl_key = lbl->key;
4525
4526     if(result) {
4527       emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4528       //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4529     }else {
4530       DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4531       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4532               __FUNCTION__,__LINE__);
4533       return;
4534     }
4535
4536 /*     switch(size) { */
4537 /*     case 2: */
4538 /*       genc16bit2lit(left, lit, 0); */
4539 /*       emitSKPNZ; */
4540 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4541 /*       break; */
4542 /*     default: */
4543     while (size--) {
4544       int emit_skip=1;
4545       if((AOP_TYPE(left) == AOP_DIR) && 
4546          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4547
4548         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4549         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4550
4551       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4552             
4553         switch (lit & 0xff) {
4554         case 0:
4555           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4556           break;
4557         case 1:
4558           emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4559           emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4560           //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4561           emit_skip=0;
4562           break;
4563         case 0xff:
4564           emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4565           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4566           //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4567           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4568           emit_skip=0;
4569           break;
4570         default:
4571           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4572           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4573         }
4574         lit >>= 8;
4575
4576       } else {
4577         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4578       }
4579       if(emit_skip) {
4580         if(AOP_TYPE(result) == AOP_CRY) {
4581           pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4582           if(rIfx.condition)
4583             emitSKPNZ;
4584           else
4585             emitSKPZ;
4586           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4587         } else {
4588           /* fix me. probably need to check result size too */
4589           //emitpcode(POC_CLRF,popGet(AOP(result),0));
4590           if(rIfx.condition)
4591             emitSKPZ;
4592           else
4593             emitSKPNZ;
4594           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4595           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4596         }
4597         if(ifx)
4598           ifx->generated=1;
4599       }
4600       emit_skip++;
4601       offset++;
4602       if(res_offset < res_size-1)
4603         res_offset++;
4604     }
4605 /*       break; */
4606 /*     } */
4607   } else if(AOP_TYPE(right) == AOP_REG &&
4608             AOP_TYPE(left) != AOP_DIR){
4609
4610     while(size--) {
4611       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4612       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4613       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4614       if(rIfx.condition)
4615         emitSKPNZ;
4616       else
4617         emitSKPZ;
4618       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4619       offset++;
4620       if(res_offset < res_size-1)
4621         res_offset++;
4622     }
4623       
4624   }else{
4625     /* right is a pointer reg need both a & b */
4626     while(size--) {
4627       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4628       if(strcmp(l,"b"))
4629         pic14_emitcode("mov","b,%s",l);
4630       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4631       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4632       offset++;
4633     }
4634   }
4635
4636   emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4637   if(!rIfx.condition)
4638     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4639
4640   emitpLabel(lbl->key);
4641
4642   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4643
4644   if(ifx)
4645     ifx->generated = 1;
4646 }
4647
4648 #if 0
4649 /*-----------------------------------------------------------------*/
4650 /* gencjne - compare and jump if not equal                         */
4651 /*-----------------------------------------------------------------*/
4652 static void gencjne(operand *left, operand *right, iCode *ifx)
4653 {
4654     symbol *tlbl  = newiTempLabel(NULL);
4655
4656     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4657     gencjneshort(left, right, lbl);
4658
4659     pic14_emitcode("mov","a,%s",one);
4660     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4661     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4662     pic14_emitcode("clr","a");
4663     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4664
4665     emitpLabel(lbl->key);
4666     emitpLabel(tlbl->key);
4667
4668 }
4669 #endif
4670
4671 /*-----------------------------------------------------------------*/
4672 /* genCmpEq - generates code for equal to                          */
4673 /*-----------------------------------------------------------------*/
4674 static void genCmpEq (iCode *ic, iCode *ifx)
4675 {
4676     operand *left, *right, *result;
4677     unsigned long lit = 0L;
4678     int size,offset=0;
4679
4680     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4681
4682     if(ifx)
4683       DEBUGpic14_emitcode ("; ifx is non-null","");
4684     else
4685       DEBUGpic14_emitcode ("; ifx is null","");
4686
4687     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4688     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4689     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4690
4691     size = max(AOP_SIZE(left),AOP_SIZE(right));
4692
4693     DEBUGpic14_AopType(__LINE__,left,right,result);
4694
4695     /* if literal, literal on the right or 
4696     if the right is in a pointer register and left 
4697     is not */
4698     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4699         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4700       operand *tmp = right ;
4701       right = left;
4702       left = tmp;
4703     }
4704
4705
4706     if(ifx && !AOP_SIZE(result)){
4707         symbol *tlbl;
4708         /* if they are both bit variables */
4709         if (AOP_TYPE(left) == AOP_CRY &&
4710             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4711             if(AOP_TYPE(right) == AOP_LIT){
4712                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4713                 if(lit == 0L){
4714                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4715                     pic14_emitcode("cpl","c");
4716                 } else if(lit == 1L) {
4717                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4718                 } else {
4719                     pic14_emitcode("clr","c");
4720                 }
4721                 /* AOP_TYPE(right) == AOP_CRY */
4722             } else {
4723                 symbol *lbl = newiTempLabel(NULL);
4724                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4725                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4726                 pic14_emitcode("cpl","c");
4727                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4728             }
4729             /* if true label then we jump if condition
4730             supplied is true */
4731             tlbl = newiTempLabel(NULL);
4732             if ( IC_TRUE(ifx) ) {
4733                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4734                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4735             } else {
4736                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4737                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4738             }
4739             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4740
4741             {
4742               /* left and right are both bit variables, result is carry */
4743               resolvedIfx rIfx;
4744               
4745               resolveIfx(&rIfx,ifx);
4746
4747               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4748               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4749               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4750               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4751               genSkipz2(&rIfx,0);
4752             }
4753         } else {
4754
4755           /* They're not both bit variables. Is the right a literal? */
4756           if(AOP_TYPE(right) == AOP_LIT) {
4757             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4758             
4759             switch(size) {
4760
4761             case 1:
4762               switch(lit & 0xff) {
4763               case 1:
4764                 if ( IC_TRUE(ifx) ) {
4765                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4766                   emitSKPNZ;
4767                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4768                 } else {
4769                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4770                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4771                 }
4772                 break;
4773               case 0xff:
4774                 if ( IC_TRUE(ifx) ) {
4775                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4776                   emitSKPNZ;
4777                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4778                 } else {
4779                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4780                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4781                 }
4782                 break;
4783               default:
4784                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4785                 if(lit)
4786                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4787                 genSkip(ifx,'z');
4788               }
4789
4790
4791               /* end of size == 1 */
4792               break;
4793               
4794             case 2:
4795               genc16bit2lit(left,lit,offset);
4796               genSkip(ifx,'z');
4797               break;
4798               /* end of size == 2 */
4799
4800             default:
4801               /* size is 4 */
4802               if(lit==0) {
4803                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4804                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4805                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4806                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4807
4808               } else {
4809
4810                 /* search for patterns that can be optimized */
4811
4812                 genc16bit2lit(left,lit,0);
4813                 lit >>= 16;
4814                 if(lit) {
4815                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4816                   //genSkip(ifx,'z');
4817                   genc16bit2lit(left,lit,2);
4818                 } else {
4819                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4820                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4821
4822                 }
4823                 
4824               }
4825
4826               genSkip(ifx,'z');
4827             }
4828           
4829             ifx->generated = 1;
4830             goto release ;
4831             
4832
4833           } else if(AOP_TYPE(right) == AOP_CRY ) {
4834             /* we know the left is not a bit, but that the right is */
4835             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4836             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4837                       popGet(AOP(right),offset));
4838             emitpcode(POC_XORLW,popGetLit(1));
4839
4840             /* if the two are equal, then W will be 0 and the Z bit is set
4841              * we could test Z now, or go ahead and check the high order bytes if
4842              * the variable we're comparing is larger than a byte. */
4843
4844             while(--size)
4845               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4846
4847             if ( IC_TRUE(ifx) ) {
4848               emitSKPNZ;
4849               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4850               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4851             } else {
4852               emitSKPZ;
4853               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4854               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4855             }
4856
4857           } else {
4858             /* They're both variables that are larger than bits */
4859             int s = size;
4860
4861             tlbl = newiTempLabel(NULL);
4862
4863             while(size--) {
4864               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4865               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4866
4867               if ( IC_TRUE(ifx) ) {
4868                 if(size) {
4869                   emitSKPZ;
4870                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4871                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4872                 } else {
4873                   emitSKPNZ;
4874                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4875                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4876                 }
4877               } else {
4878                 emitSKPZ;
4879                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4880                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4881               }
4882               offset++;
4883             }
4884             if(s>1 && IC_TRUE(ifx)) {
4885               emitpLabel(tlbl->key);
4886               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4887             }
4888           }
4889         }
4890         /* mark the icode as generated */
4891         ifx->generated = 1;
4892         goto release ;
4893     }
4894
4895     /* if they are both bit variables */
4896     if (AOP_TYPE(left) == AOP_CRY &&
4897         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4898         if(AOP_TYPE(right) == AOP_LIT){
4899             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4900             if(lit == 0L){
4901                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4902                 pic14_emitcode("cpl","c");
4903             } else if(lit == 1L) {
4904                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4905             } else {
4906                 pic14_emitcode("clr","c");
4907             }
4908             /* AOP_TYPE(right) == AOP_CRY */
4909         } else {
4910             symbol *lbl = newiTempLabel(NULL);
4911             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4912             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4913             pic14_emitcode("cpl","c");
4914             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4915         }
4916         /* c = 1 if egal */
4917         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4918             pic14_outBitC(result);
4919             goto release ;
4920         }
4921         if (ifx) {
4922             genIfxJump (ifx,"c");
4923             goto release ;
4924         }
4925         /* if the result is used in an arithmetic operation
4926         then put the result in place */
4927         pic14_outBitC(result);
4928     } else {
4929       
4930       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4931       gencjne(left,right,result,ifx);
4932 /*
4933       if(ifx) 
4934         gencjne(left,right,newiTempLabel(NULL));
4935       else {
4936         if(IC_TRUE(ifx)->key)
4937           gencjne(left,right,IC_TRUE(ifx)->key);
4938         else
4939           gencjne(left,right,IC_FALSE(ifx)->key);
4940         ifx->generated = 1;
4941         goto release ;
4942       }
4943       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4944         aopPut(AOP(result),"a",0);
4945         goto release ;
4946       }
4947
4948       if (ifx) {
4949         genIfxJump (ifx,"a");
4950         goto release ;
4951       }
4952 */
4953       /* if the result is used in an arithmetic operation
4954          then put the result in place */
4955 /*
4956       if (AOP_TYPE(result) != AOP_CRY) 
4957         pic14_outAcc(result);
4958 */
4959       /* leave the result in acc */
4960     }
4961
4962 release:
4963     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4964     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4965     freeAsmop(result,NULL,ic,TRUE);
4966 }
4967
4968 /*-----------------------------------------------------------------*/
4969 /* ifxForOp - returns the icode containing the ifx for operand     */
4970 /*-----------------------------------------------------------------*/
4971 static iCode *ifxForOp ( operand *op, iCode *ic )
4972 {
4973     /* if true symbol then needs to be assigned */
4974     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4975     if (IS_TRUE_SYMOP(op))
4976         return NULL ;
4977
4978     /* if this has register type condition and
4979     the next instruction is ifx with the same operand
4980     and live to of the operand is upto the ifx only then */
4981     if (ic->next &&
4982         ic->next->op == IFX &&
4983         IC_COND(ic->next)->key == op->key &&
4984         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4985         return ic->next;
4986
4987     if (ic->next &&
4988         ic->next->op == IFX &&
4989         IC_COND(ic->next)->key == op->key) {
4990       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4991       return ic->next;
4992     }
4993
4994     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4995     if (ic->next &&
4996         ic->next->op == IFX)
4997       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4998
4999     if (ic->next &&
5000         ic->next->op == IFX &&
5001         IC_COND(ic->next)->key == op->key) {
5002       DEBUGpic14_emitcode ("; "," key is okay");
5003       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5004                            OP_SYMBOL(op)->liveTo,
5005                            ic->next->seq);
5006     }
5007
5008
5009     return NULL;
5010 }
5011 /*-----------------------------------------------------------------*/
5012 /* genAndOp - for && operation                                     */
5013 /*-----------------------------------------------------------------*/
5014 static void genAndOp (iCode *ic)
5015 {
5016     operand *left,*right, *result;
5017 /*     symbol *tlbl; */
5018
5019     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5020     /* note here that && operations that are in an
5021     if statement are taken away by backPatchLabels
5022     only those used in arthmetic operations remain */
5023     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5024     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5025     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5026
5027     DEBUGpic14_AopType(__LINE__,left,right,result);
5028
5029     emitpcode(POC_MOVFW,popGet(AOP(left),0));
5030     emitpcode(POC_ANDFW,popGet(AOP(right),0));
5031     emitpcode(POC_MOVWF,popGet(AOP(result),0));
5032
5033     /* if both are bit variables */
5034 /*     if (AOP_TYPE(left) == AOP_CRY && */
5035 /*         AOP_TYPE(right) == AOP_CRY ) { */
5036 /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5037 /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5038 /*         pic14_outBitC(result); */
5039 /*     } else { */
5040 /*         tlbl = newiTempLabel(NULL); */
5041 /*         pic14_toBoolean(left);     */
5042 /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5043 /*         pic14_toBoolean(right); */
5044 /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5045 /*         pic14_outBitAcc(result); */
5046 /*     } */
5047
5048     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5049     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5050     freeAsmop(result,NULL,ic,TRUE);
5051 }
5052
5053
5054 /*-----------------------------------------------------------------*/
5055 /* genOrOp - for || operation                                      */
5056 /*-----------------------------------------------------------------*/
5057 /*
5058   tsd pic port -
5059   modified this code, but it doesn't appear to ever get called
5060 */
5061
5062 static void genOrOp (iCode *ic)
5063 {
5064     operand *left,*right, *result;
5065     symbol *tlbl;
5066
5067     /* note here that || operations that are in an
5068     if statement are taken away by backPatchLabels
5069     only those used in arthmetic operations remain */
5070     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5071     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5072     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5073     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5074
5075     DEBUGpic14_AopType(__LINE__,left,right,result);
5076
5077     /* if both are bit variables */
5078     if (AOP_TYPE(left) == AOP_CRY &&
5079         AOP_TYPE(right) == AOP_CRY ) {
5080       pic14_emitcode("clrc","");
5081       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5082                AOP(left)->aopu.aop_dir,
5083                AOP(left)->aopu.aop_dir);
5084       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5085                AOP(right)->aopu.aop_dir,
5086                AOP(right)->aopu.aop_dir);
5087       pic14_emitcode("setc","");
5088
5089     } else {
5090         tlbl = newiTempLabel(NULL);
5091         pic14_toBoolean(left);
5092         emitSKPZ;
5093         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5094         pic14_toBoolean(right);
5095         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5096
5097         pic14_outBitAcc(result);
5098     }
5099
5100     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5101     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5102     freeAsmop(result,NULL,ic,TRUE);            
5103 }
5104
5105 /*-----------------------------------------------------------------*/
5106 /* isLiteralBit - test if lit == 2^n                               */
5107 /*-----------------------------------------------------------------*/
5108 static int isLiteralBit(unsigned long lit)
5109 {
5110     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5111     0x100L,0x200L,0x400L,0x800L,
5112     0x1000L,0x2000L,0x4000L,0x8000L,
5113     0x10000L,0x20000L,0x40000L,0x80000L,
5114     0x100000L,0x200000L,0x400000L,0x800000L,
5115     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5116     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5117     int idx;
5118     
5119     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5120     for(idx = 0; idx < 32; idx++)
5121         if(lit == pw[idx])
5122             return idx+1;
5123     return 0;
5124 }
5125
5126 /*-----------------------------------------------------------------*/
5127 /* continueIfTrue -                                                */
5128 /*-----------------------------------------------------------------*/
5129 static void continueIfTrue (iCode *ic)
5130 {
5131     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5132     if(IC_TRUE(ic))
5133         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5134     ic->generated = 1;
5135 }
5136
5137 /*-----------------------------------------------------------------*/
5138 /* jmpIfTrue -                                                     */
5139 /*-----------------------------------------------------------------*/
5140 static void jumpIfTrue (iCode *ic)
5141 {
5142     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5143     if(!IC_TRUE(ic))
5144         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5145     ic->generated = 1;
5146 }
5147
5148 /*-----------------------------------------------------------------*/
5149 /* jmpTrueOrFalse -                                                */
5150 /*-----------------------------------------------------------------*/
5151 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5152 {
5153     // ugly but optimized by peephole
5154     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5155     if(IC_TRUE(ic)){
5156         symbol *nlbl = newiTempLabel(NULL);
5157         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5158         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5159         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5160         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5161     }
5162     else{
5163         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5164         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5165     }
5166     ic->generated = 1;
5167 }
5168
5169 /*-----------------------------------------------------------------*/
5170 /* genAnd  - code for and                                          */
5171 /*-----------------------------------------------------------------*/
5172 static void genAnd (iCode *ic, iCode *ifx)
5173 {
5174   operand *left, *right, *result;
5175   int size, offset=0;  
5176   unsigned long lit = 0L;
5177   int bytelit = 0;
5178   resolvedIfx rIfx;
5179
5180
5181   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5182   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5183   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5184   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5185
5186   resolveIfx(&rIfx,ifx);
5187
5188   /* if left is a literal & right is not then exchange them */
5189   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5190       AOP_NEEDSACC(left)) {
5191     operand *tmp = right ;
5192     right = left;
5193     left = tmp;
5194   }
5195
5196   /* if result = right then exchange them */
5197   if(pic14_sameRegs(AOP(result),AOP(right))){
5198     operand *tmp = right ;
5199     right = left;
5200     left = tmp;
5201   }
5202
5203   /* if right is bit then exchange them */
5204   if (AOP_TYPE(right) == AOP_CRY &&
5205       AOP_TYPE(left) != AOP_CRY){
5206     operand *tmp = right ;
5207     right = left;
5208     left = tmp;
5209   }
5210   if(AOP_TYPE(right) == AOP_LIT)
5211     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5212
5213   size = AOP_SIZE(result);
5214
5215   DEBUGpic14_AopType(__LINE__,left,right,result);
5216
5217   // if(bit & yy)
5218   // result = bit & yy;
5219   if (AOP_TYPE(left) == AOP_CRY){
5220     // c = bit & literal;
5221     if(AOP_TYPE(right) == AOP_LIT){
5222       if(lit & 1) {
5223         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5224           // no change
5225           goto release;
5226         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5227       } else {
5228         // bit(result) = 0;
5229         if(size && (AOP_TYPE(result) == AOP_CRY)){
5230           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5231           goto release;
5232         }
5233         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5234           jumpIfTrue(ifx);
5235           goto release;
5236         }
5237         pic14_emitcode("clr","c");
5238       }
5239     } else {
5240       if (AOP_TYPE(right) == AOP_CRY){
5241         // c = bit & bit;
5242         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5243         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5244       } else {
5245         // c = bit & val;
5246         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5247         // c = lsb
5248         pic14_emitcode("rrc","a");
5249         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5250       }
5251     }
5252     // bit = c
5253     // val = c
5254     if(size)
5255       pic14_outBitC(result);
5256     // if(bit & ...)
5257     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5258       genIfxJump(ifx, "c");           
5259     goto release ;
5260   }
5261
5262   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5263   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5264   if((AOP_TYPE(right) == AOP_LIT) &&
5265      (AOP_TYPE(result) == AOP_CRY) &&
5266      (AOP_TYPE(left) != AOP_CRY)){
5267     int posbit = isLiteralBit(lit);
5268     /* left &  2^n */
5269     if(posbit){
5270       posbit--;
5271       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5272       // bit = left & 2^n
5273       if(size)
5274         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5275         // if(left &  2^n)
5276       else{
5277         if(ifx){
5278           int offset = 0;
5279           while (posbit > 7) {
5280             posbit -= 8;
5281             offset++;
5282           }
5283           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5284             newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5285           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5286
5287           ifx->generated = 1;
5288           }
5289           goto release;
5290       }
5291     } else {
5292       symbol *tlbl = newiTempLabel(NULL);
5293       int sizel = AOP_SIZE(left);
5294       if(size)
5295         pic14_emitcode("setb","c");
5296       while(sizel--){
5297         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5298           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5299           // byte ==  2^n ?
5300           if((posbit = isLiteralBit(bytelit)) != 0)
5301             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5302           else{
5303             if(bytelit != 0x0FFL)
5304               pic14_emitcode("anl","a,%s",
5305                              aopGet(AOP(right),offset,FALSE,TRUE));
5306             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5307           }
5308         }
5309         offset++;
5310       }
5311       // bit = left & literal
5312       if(size){
5313         pic14_emitcode("clr","c");
5314         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5315       }
5316       // if(left & literal)
5317       else{
5318         if(ifx)
5319           jmpTrueOrFalse(ifx, tlbl);
5320         goto release ;
5321       }
5322     }
5323     pic14_outBitC(result);
5324     goto release ;
5325   }
5326
5327   /* if left is same as result */
5328   if(pic14_sameRegs(AOP(result),AOP(left))){
5329     int know_W = -1;
5330     for(;size--; offset++,lit>>=8) {
5331       if(AOP_TYPE(right) == AOP_LIT){
5332         switch(lit & 0xff) {
5333         case 0x00:
5334           /*  and'ing with 0 has clears the result */
5335           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5336           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5337           break;
5338         case 0xff:
5339           /* and'ing with 0xff is a nop when the result and left are the same */
5340           break;
5341
5342         default:
5343           {
5344             int p = my_powof2( (~lit) & 0xff );
5345             if(p>=0) {
5346               /* only one bit is set in the literal, so use a bcf instruction */
5347               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5348               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5349
5350             } else {
5351               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5352               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5353               if(know_W != (int)(lit&0xff))
5354                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5355               know_W = lit &0xff;
5356               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5357             }
5358           }    
5359         }
5360       } else {
5361         if (AOP_TYPE(left) == AOP_ACC) {
5362           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5363         } else {                    
5364           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5365           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5366
5367         }
5368       }
5369     }
5370
5371   } else {
5372     // left & result in different registers
5373     if(AOP_TYPE(result) == AOP_CRY){
5374       // result = bit
5375       // if(size), result in bit
5376       // if(!size && ifx), conditional oper: if(left & right)
5377       symbol *tlbl = newiTempLabel(NULL);
5378       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5379       if(size)
5380         pic14_emitcode("setb","c");
5381       while(sizer--){
5382         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5383         pic14_emitcode("anl","a,%s",
5384                        aopGet(AOP(left),offset,FALSE,FALSE));
5385         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5386         offset++;
5387       }
5388       if(size){
5389         CLRC;
5390         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5391         pic14_outBitC(result);
5392       } else if(ifx)
5393         jmpTrueOrFalse(ifx, tlbl);
5394     } else {
5395       for(;(size--);offset++) {
5396         // normal case
5397         // result = left & right
5398         if(AOP_TYPE(right) == AOP_LIT){
5399           int t = (lit >> (offset*8)) & 0x0FFL;
5400           switch(t) { 
5401           case 0x00:
5402             pic14_emitcode("clrf","%s",
5403                            aopGet(AOP(result),offset,FALSE,FALSE));
5404             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5405             break;
5406           case 0xff:
5407             if(AOP_TYPE(left) != AOP_ACC) {
5408               pic14_emitcode("movf","%s,w",
5409                              aopGet(AOP(left),offset,FALSE,FALSE));
5410               pic14_emitcode("movwf","%s",
5411                              aopGet(AOP(result),offset,FALSE,FALSE));
5412               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5413             }
5414             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5415             break;
5416           default:
5417             if(AOP_TYPE(left) == AOP_ACC) {
5418               emitpcode(POC_ANDLW, popGetLit(t));
5419             } else {
5420               pic14_emitcode("movlw","0x%x",t);
5421               pic14_emitcode("andwf","%s,w",
5422                              aopGet(AOP(left),offset,FALSE,FALSE));
5423               pic14_emitcode("movwf","%s",
5424                              aopGet(AOP(result),offset,FALSE,FALSE));
5425               
5426               emitpcode(POC_MOVLW, popGetLit(t));
5427               emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5428             }
5429             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5430           }
5431           continue;
5432         }
5433
5434         if (AOP_TYPE(left) == AOP_ACC) {
5435           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5436           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5437         } else {
5438           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5439           pic14_emitcode("andwf","%s,w",
5440                          aopGet(AOP(left),offset,FALSE,FALSE));
5441           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5442           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5443         }
5444         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5445         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5446       }
5447     }
5448   }
5449
5450   release :
5451     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5452   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5453   freeAsmop(result,NULL,ic,TRUE);     
5454 }
5455
5456 /*-----------------------------------------------------------------*/
5457 /* genOr  - code for or                                            */
5458 /*-----------------------------------------------------------------*/
5459 static void genOr (iCode *ic, iCode *ifx)
5460 {
5461     operand *left, *right, *result;
5462     int size, offset=0;
5463     unsigned long lit = 0L;
5464
5465     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5466
5467     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5468     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5469     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5470
5471     DEBUGpic14_AopType(__LINE__,left,right,result);
5472
5473     /* if left is a literal & right is not then exchange them */
5474     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5475         AOP_NEEDSACC(left)) {
5476         operand *tmp = right ;
5477         right = left;
5478         left = tmp;
5479     }
5480
5481     /* if result = right then exchange them */
5482     if(pic14_sameRegs(AOP(result),AOP(right))){
5483         operand *tmp = right ;
5484         right = left;
5485         left = tmp;
5486     }
5487
5488     /* if right is bit then exchange them */
5489     if (AOP_TYPE(right) == AOP_CRY &&
5490         AOP_TYPE(left) != AOP_CRY){
5491         operand *tmp = right ;
5492         right = left;
5493         left = tmp;
5494     }
5495
5496     DEBUGpic14_AopType(__LINE__,left,right,result);
5497
5498     if(AOP_TYPE(right) == AOP_LIT)
5499         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5500
5501     size = AOP_SIZE(result);
5502
5503     // if(bit | yy)
5504     // xx = bit | yy;
5505     if (AOP_TYPE(left) == AOP_CRY){
5506         if(AOP_TYPE(right) == AOP_LIT){
5507             // c = bit & literal;
5508             if(lit){
5509                 // lit != 0 => result = 1
5510                 if(AOP_TYPE(result) == AOP_CRY){
5511                   if(size)
5512                     emitpcode(POC_BSF, popGet(AOP(result),0));
5513                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5514                   //     AOP(result)->aopu.aop_dir,
5515                   //     AOP(result)->aopu.aop_dir);
5516                     else if(ifx)
5517                         continueIfTrue(ifx);
5518                     goto release;
5519                 }
5520             } else {
5521                 // lit == 0 => result = left
5522                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5523                     goto release;
5524                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5525             }
5526         } else {
5527             if (AOP_TYPE(right) == AOP_CRY){
5528               if(pic14_sameRegs(AOP(result),AOP(left))){
5529                 // c = bit | bit;
5530                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5531                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5532                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5533
5534                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5535                          AOP(result)->aopu.aop_dir,
5536                          AOP(result)->aopu.aop_dir);
5537                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5538                          AOP(right)->aopu.aop_dir,
5539                          AOP(right)->aopu.aop_dir);
5540                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5541                          AOP(result)->aopu.aop_dir,
5542                          AOP(result)->aopu.aop_dir);
5543               } else {
5544                 if( AOP_TYPE(result) == AOP_ACC) {
5545                   emitpcode(POC_MOVLW, popGetLit(0));
5546                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5547                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5548                   emitpcode(POC_MOVLW, popGetLit(1));
5549
5550                 } else {
5551
5552                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5553                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5554                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5555                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5556
5557                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5558                                  AOP(result)->aopu.aop_dir,
5559                                  AOP(result)->aopu.aop_dir);
5560                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5561                                  AOP(right)->aopu.aop_dir,
5562                                  AOP(right)->aopu.aop_dir);
5563                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5564                                  AOP(left)->aopu.aop_dir,
5565                                  AOP(left)->aopu.aop_dir);
5566                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5567                                  AOP(result)->aopu.aop_dir,
5568                                  AOP(result)->aopu.aop_dir);
5569                 }
5570               }
5571             } else {
5572                 // c = bit | val;
5573                 symbol *tlbl = newiTempLabel(NULL);
5574                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5575
5576
5577                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5578                 if( AOP_TYPE(right) == AOP_ACC) {
5579                   emitpcode(POC_IORLW, popGetLit(0));
5580                   emitSKPNZ;
5581                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5582                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5583                 }
5584
5585
5586
5587                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5588                     pic14_emitcode(";XXX setb","c");
5589                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5590                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5591                 pic14_toBoolean(right);
5592                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5593                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5594                     jmpTrueOrFalse(ifx, tlbl);
5595                     goto release;
5596                 } else {
5597                     CLRC;
5598                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5599                 }
5600             }
5601         }
5602         // bit = c
5603         // val = c
5604         if(size)
5605             pic14_outBitC(result);
5606         // if(bit | ...)
5607         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5608             genIfxJump(ifx, "c");           
5609         goto release ;
5610     }
5611
5612     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5613     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5614     if((AOP_TYPE(right) == AOP_LIT) &&
5615        (AOP_TYPE(result) == AOP_CRY) &&
5616        (AOP_TYPE(left) != AOP_CRY)){
5617         if(lit){
5618           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5619             // result = 1
5620             if(size)
5621                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5622             else 
5623                 continueIfTrue(ifx);
5624             goto release;
5625         } else {
5626           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5627             // lit = 0, result = boolean(left)
5628             if(size)
5629                 pic14_emitcode(";XXX setb","c");
5630             pic14_toBoolean(right);
5631             if(size){
5632                 symbol *tlbl = newiTempLabel(NULL);
5633                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5634                 CLRC;
5635                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5636             } else {
5637                 genIfxJump (ifx,"a");
5638                 goto release;
5639             }
5640         }
5641         pic14_outBitC(result);
5642         goto release ;
5643     }
5644
5645     /* if left is same as result */
5646     if(pic14_sameRegs(AOP(result),AOP(left))){
5647       int know_W = -1;
5648       for(;size--; offset++,lit>>=8) {
5649         if(AOP_TYPE(right) == AOP_LIT){
5650           if((lit & 0xff) == 0)
5651             /*  or'ing with 0 has no effect */
5652             continue;
5653           else {
5654             int p = my_powof2(lit & 0xff);
5655             if(p>=0) {
5656               /* only one bit is set in the literal, so use a bsf instruction */
5657               emitpcode(POC_BSF,
5658                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5659             } else {
5660               if(know_W != (int)(lit & 0xff))
5661                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5662               know_W = lit & 0xff;
5663               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5664             }
5665                     
5666           }
5667         } else {
5668           if (AOP_TYPE(left) == AOP_ACC) {
5669             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5670             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5671           } else {                  
5672             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5673             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5674
5675             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5676             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5677
5678           }
5679         }
5680       }
5681     } else {
5682         // left & result in different registers
5683         if(AOP_TYPE(result) == AOP_CRY){
5684             // result = bit
5685             // if(size), result in bit
5686             // if(!size && ifx), conditional oper: if(left | right)
5687             symbol *tlbl = newiTempLabel(NULL);
5688             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5689             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5690
5691
5692             if(size)
5693                 pic14_emitcode(";XXX setb","c");
5694             while(sizer--){
5695                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5696                 pic14_emitcode(";XXX orl","a,%s",
5697                          aopGet(AOP(left),offset,FALSE,FALSE));
5698                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5699                 offset++;
5700             }
5701             if(size){
5702                 CLRC;
5703                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5704                 pic14_outBitC(result);
5705             } else if(ifx)
5706                 jmpTrueOrFalse(ifx, tlbl);
5707         } else for(;(size--);offset++){
5708           // normal case
5709           // result = left & right
5710           if(AOP_TYPE(right) == AOP_LIT){
5711             int t = (lit >> (offset*8)) & 0x0FFL;
5712             switch(t) { 
5713             case 0x00:
5714               if (AOP_TYPE(left) != AOP_ACC) {
5715                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5716               }
5717               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5718
5719               break;
5720             default:
5721               if (AOP_TYPE(left) == AOP_ACC) {
5722                 emitpcode(POC_IORLW,  popGetLit(t));
5723               } else {
5724                 emitpcode(POC_MOVLW,  popGetLit(t));
5725                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5726               }
5727               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));              
5728             }
5729             continue;
5730           }
5731
5732           // faster than result <- left, anl result,right
5733           // and better if result is SFR
5734           if (AOP_TYPE(left) == AOP_ACC) {
5735             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5736             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5737           } else {
5738             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5739             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5740
5741             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5742             pic14_emitcode("iorwf","%s,w",
5743                      aopGet(AOP(left),offset,FALSE,FALSE));
5744           }
5745           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5746           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5747         }
5748     }
5749
5750 release :
5751     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5752     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5753     freeAsmop(result,NULL,ic,TRUE);     
5754 }
5755
5756 /*-----------------------------------------------------------------*/
5757 /* genXor - code for xclusive or                                   */
5758 /*-----------------------------------------------------------------*/
5759 static void genXor (iCode *ic, iCode *ifx)
5760 {
5761   operand *left, *right, *result;
5762   int size, offset=0;
5763   unsigned long lit = 0L;
5764
5765   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5766
5767   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5768   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5769   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5770
5771   /* if left is a literal & right is not ||
5772      if left needs acc & right does not */
5773   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5774       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5775     operand *tmp = right ;
5776     right = left;
5777     left = tmp;
5778   }
5779
5780   /* if result = right then exchange them */
5781   if(pic14_sameRegs(AOP(result),AOP(right))){
5782     operand *tmp = right ;
5783     right = left;
5784     left = tmp;
5785   }
5786
5787   /* if right is bit then exchange them */
5788   if (AOP_TYPE(right) == AOP_CRY &&
5789       AOP_TYPE(left) != AOP_CRY){
5790     operand *tmp = right ;
5791     right = left;
5792     left = tmp;
5793   }
5794   if(AOP_TYPE(right) == AOP_LIT)
5795     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5796
5797   size = AOP_SIZE(result);
5798
5799   // if(bit ^ yy)
5800   // xx = bit ^ yy;
5801   if (AOP_TYPE(left) == AOP_CRY){
5802     if(AOP_TYPE(right) == AOP_LIT){
5803       // c = bit & literal;
5804       if(lit>>1){
5805         // lit>>1  != 0 => result = 1
5806         if(AOP_TYPE(result) == AOP_CRY){
5807           if(size)
5808             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5809             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5810           else if(ifx)
5811             continueIfTrue(ifx);
5812           goto release;
5813         }
5814         pic14_emitcode("setb","c");
5815       } else{
5816         // lit == (0 or 1)
5817         if(lit == 0){
5818           // lit == 0, result = left
5819           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5820             goto release;
5821           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5822         } else{
5823           // lit == 1, result = not(left)
5824           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5825             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5826             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5827             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5828             goto release;
5829           } else {
5830             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5831             pic14_emitcode("cpl","c");
5832           }
5833         }
5834       }
5835
5836     } else {
5837       // right != literal
5838       symbol *tlbl = newiTempLabel(NULL);
5839       if (AOP_TYPE(right) == AOP_CRY){
5840         // c = bit ^ bit;
5841         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5842       }
5843       else{
5844         int sizer = AOP_SIZE(right);
5845         // c = bit ^ val
5846         // if val>>1 != 0, result = 1
5847         pic14_emitcode("setb","c");
5848         while(sizer){
5849           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5850           if(sizer == 1)
5851             // test the msb of the lsb
5852             pic14_emitcode("anl","a,#0xfe");
5853           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5854           sizer--;
5855         }
5856         // val = (0,1)
5857         pic14_emitcode("rrc","a");
5858       }
5859       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5860       pic14_emitcode("cpl","c");
5861       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5862     }
5863     // bit = c
5864     // val = c
5865     if(size)
5866       pic14_outBitC(result);
5867     // if(bit | ...)
5868     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5869       genIfxJump(ifx, "c");           
5870     goto release ;
5871   }
5872
5873   if(pic14_sameRegs(AOP(result),AOP(left))){
5874     /* if left is same as result */
5875     for(;size--; offset++) {
5876       if(AOP_TYPE(right) == AOP_LIT){
5877         int t  = (lit >> (offset*8)) & 0x0FFL;
5878         if(t == 0x00L)
5879           continue;
5880         else
5881           if (IS_AOP_PREG(left)) {
5882             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5883             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5884             aopPut(AOP(result),"a",offset);
5885           } else {
5886             emitpcode(POC_MOVLW, popGetLit(t));
5887             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5888             pic14_emitcode("xrl","%s,%s",
5889                            aopGet(AOP(left),offset,FALSE,TRUE),
5890                            aopGet(AOP(right),offset,FALSE,FALSE));
5891           }
5892       } else {
5893         if (AOP_TYPE(left) == AOP_ACC)
5894           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5895         else {
5896           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5897           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5898 /*
5899           if (IS_AOP_PREG(left)) {
5900             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5901             aopPut(AOP(result),"a",offset);
5902           } else
5903             pic14_emitcode("xrl","%s,a",
5904                            aopGet(AOP(left),offset,FALSE,TRUE));
5905 */
5906         }
5907       }
5908     }
5909   } else {
5910     // left & result in different registers
5911     if(AOP_TYPE(result) == AOP_CRY){
5912       // result = bit
5913       // if(size), result in bit
5914       // if(!size && ifx), conditional oper: if(left ^ right)
5915       symbol *tlbl = newiTempLabel(NULL);
5916       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5917       if(size)
5918         pic14_emitcode("setb","c");
5919       while(sizer--){
5920         if((AOP_TYPE(right) == AOP_LIT) &&
5921            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5922           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5923         } else {
5924           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5925           pic14_emitcode("xrl","a,%s",
5926                          aopGet(AOP(left),offset,FALSE,FALSE));
5927         }
5928         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5929         offset++;
5930       }
5931       if(size){
5932         CLRC;
5933         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5934         pic14_outBitC(result);
5935       } else if(ifx)
5936         jmpTrueOrFalse(ifx, tlbl);
5937     } else for(;(size--);offset++){
5938       // normal case
5939       // result = left & right
5940       if(AOP_TYPE(right) == AOP_LIT){
5941         int t = (lit >> (offset*8)) & 0x0FFL;
5942         switch(t) { 
5943         case 0x00:
5944           if (AOP_TYPE(left) != AOP_ACC) {
5945             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5946           }
5947           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5948           pic14_emitcode("movf","%s,w",
5949                          aopGet(AOP(left),offset,FALSE,FALSE));
5950           pic14_emitcode("movwf","%s",
5951                          aopGet(AOP(result),offset,FALSE,FALSE));
5952           break;
5953         case 0xff:
5954           if (AOP_TYPE(left) == AOP_ACC) {
5955             emitpcode(POC_XORLW, popGetLit(t));
5956           } else {
5957             emitpcode(POC_COMFW,popGet(AOP(left),offset));
5958           }
5959           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5960           break;
5961         default:
5962           if (AOP_TYPE(left) == AOP_ACC) {
5963             emitpcode(POC_XORLW, popGetLit(t));
5964           } else {
5965             emitpcode(POC_MOVLW, popGetLit(t));
5966             emitpcode(POC_XORFW,popGet(AOP(left),offset));
5967           }
5968           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5969           pic14_emitcode("movlw","0x%x",t);
5970           pic14_emitcode("xorwf","%s,w",
5971                          aopGet(AOP(left),offset,FALSE,FALSE));
5972           pic14_emitcode("movwf","%s",
5973                          aopGet(AOP(result),offset,FALSE,FALSE));
5974
5975         }
5976         continue;
5977       }
5978
5979       // faster than result <- left, anl result,right
5980       // and better if result is SFR
5981       if (AOP_TYPE(left) == AOP_ACC) {
5982         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5983         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5984       } else {
5985         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5986         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5987         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5988         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5989       }
5990       if ( AOP_TYPE(result) != AOP_ACC){
5991         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5992         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5993       }
5994     }
5995   }
5996
5997   release :
5998     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5999   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6000   freeAsmop(result,NULL,ic,TRUE);     
6001 }
6002
6003 /*-----------------------------------------------------------------*/
6004 /* genInline - write the inline code out                           */
6005 /*-----------------------------------------------------------------*/
6006 static void genInline (iCode *ic)
6007 {
6008     char *buffer, *bp, *bp1;
6009     
6010     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6011
6012     _G.inLine += (!options.asmpeep);
6013
6014     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6015     strcpy(buffer,IC_INLINE(ic));
6016
6017     /* emit each line as a code */
6018     while (*bp) {
6019         if (*bp == '\n') {
6020             *bp++ = '\0';
6021
6022             if(*bp1)
6023               addpCode2pBlock(pb,AssembleLine(bp1));
6024             bp1 = bp;
6025         } else {
6026             if (*bp == ':') {
6027                 bp++;
6028                 *bp = '\0';
6029                 bp++;
6030                 pic14_emitcode(bp1,"");
6031                 bp1 = bp;
6032             } else
6033                 bp++;
6034         }
6035     }
6036     if ((bp1 != bp) && *bp1)
6037       addpCode2pBlock(pb,AssembleLine(bp1));
6038
6039     Safe_free(buffer);
6040
6041     _G.inLine -= (!options.asmpeep);
6042 }
6043
6044 /*-----------------------------------------------------------------*/
6045 /* genRRC - rotate right with carry                                */
6046 /*-----------------------------------------------------------------*/
6047 static void genRRC (iCode *ic)
6048 {
6049   operand *left , *result ;
6050   int size, offset = 0, same;
6051
6052   /* rotate right with carry */
6053   left = IC_LEFT(ic);
6054   result=IC_RESULT(ic);
6055   aopOp (left,ic,FALSE);
6056   aopOp (result,ic,FALSE);
6057
6058   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6059
6060   same = pic14_sameRegs(AOP(result),AOP(left));
6061
6062   size = AOP_SIZE(result);    
6063
6064   /* get the lsb and put it into the carry */
6065   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6066
6067   offset = 0 ;
6068
6069   while(size--) {
6070
6071     if(same) {
6072       emitpcode(POC_RRF, popGet(AOP(left),offset));
6073     } else {
6074       emitpcode(POC_RRFW, popGet(AOP(left),offset));
6075       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6076     }
6077
6078     offset++;
6079   }
6080
6081   freeAsmop(left,NULL,ic,TRUE);
6082   freeAsmop(result,NULL,ic,TRUE);
6083 }
6084
6085 /*-----------------------------------------------------------------*/
6086 /* genRLC - generate code for rotate left with carry               */
6087 /*-----------------------------------------------------------------*/
6088 static void genRLC (iCode *ic)
6089 {    
6090   operand *left , *result ;
6091   int size, offset = 0;
6092   int same;
6093
6094   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6095   /* rotate right with carry */
6096   left = IC_LEFT(ic);
6097   result=IC_RESULT(ic);
6098   aopOp (left,ic,FALSE);
6099   aopOp (result,ic,FALSE);
6100
6101   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6102
6103   same = pic14_sameRegs(AOP(result),AOP(left));
6104
6105   /* move it to the result */
6106   size = AOP_SIZE(result);    
6107
6108   /* get the msb and put it into the carry */
6109   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6110
6111   offset = 0 ;
6112
6113   while(size--) {
6114
6115     if(same) {
6116       emitpcode(POC_RLF, popGet(AOP(left),offset));
6117     } else {
6118       emitpcode(POC_RLFW, popGet(AOP(left),offset));
6119       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6120     }
6121
6122     offset++;
6123   }
6124
6125
6126   freeAsmop(left,NULL,ic,TRUE);
6127   freeAsmop(result,NULL,ic,TRUE);
6128 }
6129
6130 /*-----------------------------------------------------------------*/
6131 /* genGetHbit - generates code get highest order bit               */
6132 /*-----------------------------------------------------------------*/
6133 static void genGetHbit (iCode *ic)
6134 {
6135     operand *left, *result;
6136     left = IC_LEFT(ic);
6137     result=IC_RESULT(ic);
6138     aopOp (left,ic,FALSE);
6139     aopOp (result,ic,FALSE);
6140
6141     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6142     /* get the highest order byte into a */
6143     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6144     if(AOP_TYPE(result) == AOP_CRY){
6145         pic14_emitcode("rlc","a");
6146         pic14_outBitC(result);
6147     }
6148     else{
6149         pic14_emitcode("rl","a");
6150         pic14_emitcode("anl","a,#0x01");
6151         pic14_outAcc(result);
6152     }
6153
6154
6155     freeAsmop(left,NULL,ic,TRUE);
6156     freeAsmop(result,NULL,ic,TRUE);
6157 }
6158
6159 /*-----------------------------------------------------------------*/
6160 /* AccRol - rotate left accumulator by known count                 */
6161 /*-----------------------------------------------------------------*/
6162 static void AccRol (int shCount)
6163 {
6164     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6165     shCount &= 0x0007;              // shCount : 0..7
6166     switch(shCount){
6167         case 0 :
6168             break;
6169         case 1 :
6170             pic14_emitcode("rl","a");
6171             break;
6172         case 2 :
6173             pic14_emitcode("rl","a");
6174             pic14_emitcode("rl","a");
6175             break;
6176         case 3 :
6177             pic14_emitcode("swap","a");
6178             pic14_emitcode("rr","a");
6179             break;
6180         case 4 :
6181             pic14_emitcode("swap","a");
6182             break;
6183         case 5 :
6184             pic14_emitcode("swap","a");
6185             pic14_emitcode("rl","a");
6186             break;
6187         case 6 :
6188             pic14_emitcode("rr","a");
6189             pic14_emitcode("rr","a");
6190             break;
6191         case 7 :
6192             pic14_emitcode("rr","a");
6193             break;
6194     }
6195 }
6196
6197 /*-----------------------------------------------------------------*/
6198 /* AccLsh - left shift accumulator by known count                  */
6199 /*-----------------------------------------------------------------*/
6200 static void AccLsh (int shCount)
6201 {
6202     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6203     if(shCount != 0){
6204         if(shCount == 1)
6205             pic14_emitcode("add","a,acc");
6206         else 
6207             if(shCount == 2) {
6208             pic14_emitcode("add","a,acc");
6209             pic14_emitcode("add","a,acc");
6210         } else {
6211             /* rotate left accumulator */
6212             AccRol(shCount);
6213             /* and kill the lower order bits */
6214             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6215         }
6216     }
6217 }
6218
6219 /*-----------------------------------------------------------------*/
6220 /* AccRsh - right shift accumulator by known count                 */
6221 /*-----------------------------------------------------------------*/
6222 static void AccRsh (int shCount)
6223 {
6224     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6225     if(shCount != 0){
6226         if(shCount == 1){
6227             CLRC;
6228             pic14_emitcode("rrc","a");
6229         } else {
6230             /* rotate right accumulator */
6231             AccRol(8 - shCount);
6232             /* and kill the higher order bits */
6233             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6234         }
6235     }
6236 }
6237
6238 #if 0
6239 /*-----------------------------------------------------------------*/
6240 /* AccSRsh - signed right shift accumulator by known count                 */
6241 /*-----------------------------------------------------------------*/
6242 static void AccSRsh (int shCount)
6243 {
6244     symbol *tlbl ;
6245     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6246     if(shCount != 0){
6247         if(shCount == 1){
6248             pic14_emitcode("mov","c,acc.7");
6249             pic14_emitcode("rrc","a");
6250         } else if(shCount == 2){
6251             pic14_emitcode("mov","c,acc.7");
6252             pic14_emitcode("rrc","a");
6253             pic14_emitcode("mov","c,acc.7");
6254             pic14_emitcode("rrc","a");
6255         } else {
6256             tlbl = newiTempLabel(NULL);
6257             /* rotate right accumulator */
6258             AccRol(8 - shCount);
6259             /* and kill the higher order bits */
6260             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6261             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6262             pic14_emitcode("orl","a,#0x%02x",
6263                      (unsigned char)~SRMask[shCount]);
6264             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6265         }
6266     }
6267 }
6268 #endif
6269 /*-----------------------------------------------------------------*/
6270 /* shiftR1Left2Result - shift right one byte from left to result   */
6271 /*-----------------------------------------------------------------*/
6272 static void shiftR1Left2ResultSigned (operand *left, int offl,
6273                                 operand *result, int offr,
6274                                 int shCount)
6275 {
6276   int same;
6277
6278   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6279
6280   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6281
6282   switch(shCount) {
6283   case 1:
6284     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6285     if(same) 
6286       emitpcode(POC_RRF, popGet(AOP(result),offr));
6287     else {
6288       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6289       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6290     }
6291
6292     break;
6293   case 2:
6294
6295     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6296     if(same) 
6297       emitpcode(POC_RRF, popGet(AOP(result),offr));
6298     else {
6299       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6300       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6301     }
6302     emitpcode(POC_RLFW, popGet(AOP(result),offr));
6303     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6304
6305     break;
6306
6307   case 3:
6308     if(same)
6309       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6310     else {
6311       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6312       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6313     }
6314
6315     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6316     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6317     emitpcode(POC_ANDLW, popGetLit(0x1f));
6318
6319     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6320     emitpcode(POC_IORLW, popGetLit(0xe0));
6321
6322     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6323     break;
6324
6325   case 4:
6326     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6327     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6328     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6329     emitpcode(POC_IORLW,  popGetLit(0xf0));
6330     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6331     break;
6332   case 5:
6333     if(same) {
6334       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6335     } else {
6336       emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6337       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6338     }
6339     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6340     emitpcode(POC_ANDLW,  popGetLit(0x07));
6341     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6342     emitpcode(POC_IORLW,  popGetLit(0xf8));
6343     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6344     break;
6345
6346   case 6:
6347     if(same) {
6348       emitpcode(POC_MOVLW, popGetLit(0x00));
6349       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6350       emitpcode(POC_MOVLW, popGetLit(0xfe));
6351       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6352       emitpcode(POC_IORLW, popGetLit(0x01));
6353       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6354     } else {
6355       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6356       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6357       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6358       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6359       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6360     }
6361     break;
6362
6363   case 7:
6364     if(same) {
6365       emitpcode(POC_MOVLW, popGetLit(0x00));
6366       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6367       emitpcode(POC_MOVLW, popGetLit(0xff));
6368       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6369     } else {
6370       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6371       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6372       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6373     }
6374
6375   default:
6376     break;
6377   }
6378 }
6379
6380 /*-----------------------------------------------------------------*/
6381 /* shiftR1Left2Result - shift right one byte from left to result   */
6382 /*-----------------------------------------------------------------*/
6383 static void shiftR1Left2Result (operand *left, int offl,
6384                                 operand *result, int offr,
6385                                 int shCount, int sign)
6386 {
6387   int same;
6388
6389   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6390
6391   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6392
6393   /* Copy the msb into the carry if signed. */
6394   if(sign) {
6395     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6396     return;
6397   }
6398
6399
6400
6401   switch(shCount) {
6402   case 1:
6403     emitCLRC;
6404     if(same) 
6405       emitpcode(POC_RRF, popGet(AOP(result),offr));
6406     else {
6407       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6408       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6409     }
6410     break;
6411   case 2:
6412     emitCLRC;
6413     if(same) {
6414       emitpcode(POC_RRF, popGet(AOP(result),offr));
6415     } else {
6416       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6417       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6418     }
6419     emitCLRC;
6420     emitpcode(POC_RRF, popGet(AOP(result),offr));
6421
6422     break;
6423   case 3:
6424     if(same)
6425       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6426     else {
6427       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6428       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6429     }
6430
6431     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6432     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6433     emitpcode(POC_ANDLW, popGetLit(0x1f));
6434     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6435     break;
6436       
6437   case 4:
6438     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6439     emitpcode(POC_ANDLW, popGetLit(0x0f));
6440     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6441     break;
6442
6443   case 5:
6444     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6445     emitpcode(POC_ANDLW, popGetLit(0x0f));
6446     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6447     emitCLRC;
6448     emitpcode(POC_RRF, popGet(AOP(result),offr));
6449
6450     break;
6451   case 6:
6452
6453     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6454     emitpcode(POC_ANDLW, popGetLit(0x80));
6455     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6456     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6457     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6458     break;
6459
6460   case 7:
6461
6462     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6463     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6464     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6465
6466     break;
6467
6468   default:
6469     break;
6470   }
6471 }
6472
6473 /*-----------------------------------------------------------------*/
6474 /* shiftL1Left2Result - shift left one byte from left to result    */
6475 /*-----------------------------------------------------------------*/
6476 static void shiftL1Left2Result (operand *left, int offl,
6477                                 operand *result, int offr, int shCount)
6478 {
6479   int same;
6480
6481   //    char *l;
6482   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6483
6484   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6485   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6486     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6487     //    MOVA(l);
6488     /* shift left accumulator */
6489     //AccLsh(shCount); // don't comment out just yet...
6490   //    aopPut(AOP(result),"a",offr);
6491
6492   switch(shCount) {
6493   case 1:
6494     /* Shift left 1 bit position */
6495     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6496     if(same) {
6497       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6498     } else {
6499       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6500       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6501     }
6502     break;
6503   case 2:
6504     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6505     emitpcode(POC_ANDLW,popGetLit(0x7e));
6506     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6507     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6508     break;
6509   case 3:
6510     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6511     emitpcode(POC_ANDLW,popGetLit(0x3e));
6512     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6513     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6514     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6515     break;
6516   case 4:
6517     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6518     emitpcode(POC_ANDLW, popGetLit(0xf0));
6519     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6520     break;
6521   case 5:
6522     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6523     emitpcode(POC_ANDLW, popGetLit(0xf0));
6524     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6525     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6526     break;
6527   case 6:
6528     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6529     emitpcode(POC_ANDLW, popGetLit(0x30));
6530     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6531     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6532     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6533     break;
6534   case 7:
6535     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6536     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6537     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6538     break;
6539
6540   default:
6541     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6542   }
6543
6544 }
6545
6546 /*-----------------------------------------------------------------*/
6547 /* movLeft2Result - move byte from left to result                  */
6548 /*-----------------------------------------------------------------*/
6549 static void movLeft2Result (operand *left, int offl,
6550                             operand *result, int offr)
6551 {
6552   char *l;
6553   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6554   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6555     l = aopGet(AOP(left),offl,FALSE,FALSE);
6556
6557     if (*l == '@' && (IS_AOP_PREG(result))) {
6558       pic14_emitcode("mov","a,%s",l);
6559       aopPut(AOP(result),"a",offr);
6560     } else {
6561       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6562       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6563     }
6564   }
6565 }
6566
6567 /*-----------------------------------------------------------------*/
6568 /* shiftL2Left2Result - shift left two bytes from left to result   */
6569 /*-----------------------------------------------------------------*/
6570 static void shiftL2Left2Result (operand *left, int offl,
6571                                 operand *result, int offr, int shCount)
6572 {
6573
6574
6575   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6576
6577   if(pic14_sameRegs(AOP(result), AOP(left))) {
6578     switch(shCount) {
6579     case 0:
6580       break;
6581     case 1:
6582     case 2:
6583     case 3:
6584
6585       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6586       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6587       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6588
6589       while(--shCount) {
6590         emitCLRC;
6591         emitpcode(POC_RLF, popGet(AOP(result),offr));
6592         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6593       }
6594
6595       break;
6596     case 4:
6597     case 5:
6598       emitpcode(POC_MOVLW, popGetLit(0x0f));
6599       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6600       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6601       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6602       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6603       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6604       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6605       if(shCount >=5) {
6606         emitpcode(POC_RLF, popGet(AOP(result),offr));
6607         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6608       }
6609       break;
6610     case 6:
6611       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6612       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6613       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6614       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6615       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6616       emitpcode(POC_ANDLW,popGetLit(0xc0));
6617       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6618       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6619       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6620       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6621       break;
6622     case 7:
6623       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6624       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6625       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6626       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6627       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6628     }
6629
6630   } else {
6631     switch(shCount) {
6632     case 0:
6633       break;
6634     case 1:
6635     case 2:
6636     case 3:
6637       /* note, use a mov/add for the shift since the mov has a
6638          chance of getting optimized out */
6639       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6640       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6641       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6642       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6643       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6644
6645       while(--shCount) {
6646         emitCLRC;
6647         emitpcode(POC_RLF, popGet(AOP(result),offr));
6648         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6649       }
6650       break;
6651
6652     case 4:
6653     case 5:
6654       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6655       emitpcode(POC_ANDLW, popGetLit(0xF0));
6656       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6657       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6658       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6659       emitpcode(POC_ANDLW, popGetLit(0xF0));
6660       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6661       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6662
6663
6664       if(shCount == 5) {
6665         emitpcode(POC_RLF, popGet(AOP(result),offr));
6666         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6667       }
6668       break;
6669     case 6:
6670       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6671       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6672       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6673       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6674
6675       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6676       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6677       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6678       emitpcode(POC_ANDLW,popGetLit(0xc0));
6679       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6680       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6681       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6682       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6683       break;
6684     case 7:
6685       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6686       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6687       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6688       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6689       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6690     }
6691   }
6692
6693 }
6694 /*-----------------------------------------------------------------*/
6695 /* shiftR2Left2Result - shift right two bytes from left to result  */
6696 /*-----------------------------------------------------------------*/
6697 static void shiftR2Left2Result (operand *left, int offl,
6698                                 operand *result, int offr,
6699                                 int shCount, int sign)
6700 {
6701   int same=0;
6702
6703   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6704   same = pic14_sameRegs(AOP(result), AOP(left));
6705
6706   if(same && ((offl + MSB16) == offr)){
6707     same=1;
6708     /* don't crash result[offr] */
6709     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6710     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6711   }
6712 /* else {
6713     movLeft2Result(left,offl, result, offr);
6714     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6715   }
6716 */
6717   /* a:x >> shCount (x = lsb(result))*/
6718 /*
6719   if(sign)
6720     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6721   else {
6722     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6723 */
6724   switch(shCount) {
6725   case 0:
6726     break;
6727   case 1:
6728   case 2:
6729   case 3:
6730     if(sign)
6731       emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6732     else
6733       emitCLRC;
6734
6735     if(same) {
6736       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6737       emitpcode(POC_RRF,popGet(AOP(result),offr));
6738     } else {
6739       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6740       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6741       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6742       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6743     }
6744
6745     while(--shCount) {
6746       if(sign)
6747         emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6748       else
6749         emitCLRC;
6750       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6751       emitpcode(POC_RRF,popGet(AOP(result),offr));
6752     }
6753     break;
6754   case 4:
6755   case 5:
6756     if(same) {
6757
6758       emitpcode(POC_MOVLW, popGetLit(0xf0));
6759       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6760       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6761
6762       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6763       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6764       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6765       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6766     } else {
6767       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6768       emitpcode(POC_ANDLW, popGetLit(0x0f));
6769       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6770
6771       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6772       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6773       emitpcode(POC_ANDLW, popGetLit(0xf0));
6774       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6775       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6776     }
6777
6778     if(shCount >=5) {
6779       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6780       emitpcode(POC_RRF, popGet(AOP(result),offr));
6781     }
6782
6783     if(sign) {
6784       emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6785       emitpcode(POC_BTFSC, 
6786                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6787       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6788     }
6789
6790     break;
6791
6792   case 6:
6793     if(same) {
6794
6795       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6796       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6797
6798       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6799       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6800       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6801       emitpcode(POC_ANDLW,popGetLit(0x03));
6802       if(sign) {
6803         emitpcode(POC_BTFSC, 
6804                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6805         emitpcode(POC_IORLW,popGetLit(0xfc));
6806       }
6807       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6808       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6809       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6810       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6811     } else {
6812       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6813       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6814       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6815       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6816       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6817       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6818       emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6819       emitpcode(POC_ANDLW,popGetLit(0x03));
6820       if(sign) {
6821         emitpcode(POC_BTFSC, 
6822                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6823         emitpcode(POC_IORLW,popGetLit(0xfc));
6824       }
6825       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6826       //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6827
6828         
6829     }
6830
6831     break;
6832   case 7:
6833     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6834     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6835     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6836     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6837     if(sign) {
6838       emitSKPNC;
6839       emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6840     } else 
6841       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6842   }
6843 }
6844
6845
6846 /*-----------------------------------------------------------------*/
6847 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6848 /*-----------------------------------------------------------------*/
6849 static void shiftLLeftOrResult (operand *left, int offl,
6850                                 operand *result, int offr, int shCount)
6851 {
6852     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6853     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6854     /* shift left accumulator */
6855     AccLsh(shCount);
6856     /* or with result */
6857     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6858     /* back to result */
6859     aopPut(AOP(result),"a",offr);
6860 }
6861
6862 /*-----------------------------------------------------------------*/
6863 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6864 /*-----------------------------------------------------------------*/
6865 static void shiftRLeftOrResult (operand *left, int offl,
6866                                 operand *result, int offr, int shCount)
6867 {
6868     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6869     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6870     /* shift right accumulator */
6871     AccRsh(shCount);
6872     /* or with result */
6873     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6874     /* back to result */
6875     aopPut(AOP(result),"a",offr);
6876 }
6877
6878 /*-----------------------------------------------------------------*/
6879 /* genlshOne - left shift a one byte quantity by known count       */
6880 /*-----------------------------------------------------------------*/
6881 static void genlshOne (operand *result, operand *left, int shCount)
6882 {       
6883     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6884     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6885 }
6886
6887 /*-----------------------------------------------------------------*/
6888 /* genlshTwo - left shift two bytes by known amount != 0           */
6889 /*-----------------------------------------------------------------*/
6890 static void genlshTwo (operand *result,operand *left, int shCount)
6891 {
6892     int size;
6893     
6894     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6895     size = pic14_getDataSize(result);
6896
6897     /* if shCount >= 8 */
6898     if (shCount >= 8) {
6899         shCount -= 8 ;
6900
6901         if (size > 1){
6902             if (shCount)
6903                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6904             else 
6905                 movLeft2Result(left, LSB, result, MSB16);
6906         }
6907         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6908     }
6909
6910     /*  1 <= shCount <= 7 */
6911     else {  
6912         if(size == 1)
6913             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6914         else 
6915             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6916     }
6917 }
6918
6919 /*-----------------------------------------------------------------*/
6920 /* shiftLLong - shift left one long from left to result            */
6921 /* offl = LSB or MSB16                                             */
6922 /*-----------------------------------------------------------------*/
6923 static void shiftLLong (operand *left, operand *result, int offr )
6924 {
6925     char *l;
6926     int size = AOP_SIZE(result);
6927
6928     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6929     if(size >= LSB+offr){
6930         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6931         MOVA(l);
6932         pic14_emitcode("add","a,acc");
6933         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6934             size >= MSB16+offr && offr != LSB )
6935             pic14_emitcode("xch","a,%s",
6936                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6937         else        
6938             aopPut(AOP(result),"a",LSB+offr);
6939     }
6940
6941     if(size >= MSB16+offr){
6942         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6943             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6944             MOVA(l);
6945         }
6946         pic14_emitcode("rlc","a");
6947         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6948             size >= MSB24+offr && offr != LSB)
6949             pic14_emitcode("xch","a,%s",
6950                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6951         else        
6952             aopPut(AOP(result),"a",MSB16+offr);
6953     }
6954
6955     if(size >= MSB24+offr){
6956         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6957             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6958             MOVA(l);
6959         }
6960         pic14_emitcode("rlc","a");
6961         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6962             size >= MSB32+offr && offr != LSB )
6963             pic14_emitcode("xch","a,%s",
6964                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6965         else        
6966             aopPut(AOP(result),"a",MSB24+offr);
6967     }
6968
6969     if(size > MSB32+offr){
6970         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6971             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6972             MOVA(l);    
6973         }
6974         pic14_emitcode("rlc","a");
6975         aopPut(AOP(result),"a",MSB32+offr);
6976     }
6977     if(offr != LSB)
6978         aopPut(AOP(result),zero,LSB);       
6979 }
6980
6981 /*-----------------------------------------------------------------*/
6982 /* genlshFour - shift four byte by a known amount != 0             */
6983 /*-----------------------------------------------------------------*/
6984 static void genlshFour (operand *result, operand *left, int shCount)
6985 {
6986     int size;
6987
6988     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6989     size = AOP_SIZE(result);
6990
6991     /* if shifting more that 3 bytes */
6992     if (shCount >= 24 ) {
6993         shCount -= 24;
6994         if (shCount)
6995             /* lowest order of left goes to the highest
6996             order of the destination */
6997             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6998         else
6999             movLeft2Result(left, LSB, result, MSB32);
7000         aopPut(AOP(result),zero,LSB);
7001         aopPut(AOP(result),zero,MSB16);
7002         aopPut(AOP(result),zero,MSB32);
7003         return;
7004     }
7005
7006     /* more than two bytes */
7007     else if ( shCount >= 16 ) {
7008         /* lower order two bytes goes to higher order two bytes */
7009         shCount -= 16;
7010         /* if some more remaining */
7011         if (shCount)
7012             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7013         else {
7014             movLeft2Result(left, MSB16, result, MSB32);
7015             movLeft2Result(left, LSB, result, MSB24);
7016         }
7017         aopPut(AOP(result),zero,MSB16);
7018         aopPut(AOP(result),zero,LSB);
7019         return;
7020     }    
7021
7022     /* if more than 1 byte */
7023     else if ( shCount >= 8 ) {
7024         /* lower order three bytes goes to higher order  three bytes */
7025         shCount -= 8;
7026         if(size == 2){
7027             if(shCount)
7028                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7029             else
7030                 movLeft2Result(left, LSB, result, MSB16);
7031         }
7032         else{   /* size = 4 */
7033             if(shCount == 0){
7034                 movLeft2Result(left, MSB24, result, MSB32);
7035                 movLeft2Result(left, MSB16, result, MSB24);
7036                 movLeft2Result(left, LSB, result, MSB16);
7037                 aopPut(AOP(result),zero,LSB);
7038             }
7039             else if(shCount == 1)
7040                 shiftLLong(left, result, MSB16);
7041             else{
7042                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7043                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7044                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7045                 aopPut(AOP(result),zero,LSB);
7046             }
7047         }
7048     }
7049
7050     /* 1 <= shCount <= 7 */
7051     else if(shCount <= 2){
7052         shiftLLong(left, result, LSB);
7053         if(shCount == 2)
7054             shiftLLong(result, result, LSB);
7055     }
7056     /* 3 <= shCount <= 7, optimize */
7057     else{
7058         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7059         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7060         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7061     }
7062 }
7063
7064 /*-----------------------------------------------------------------*/
7065 /* genLeftShiftLiteral - left shifting by known count              */
7066 /*-----------------------------------------------------------------*/
7067 static void genLeftShiftLiteral (operand *left,
7068                                  operand *right,
7069                                  operand *result,
7070                                  iCode *ic)
7071 {    
7072     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7073     int size;
7074
7075     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7076     freeAsmop(right,NULL,ic,TRUE);
7077
7078     aopOp(left,ic,FALSE);
7079     aopOp(result,ic,FALSE);
7080
7081     size = getSize(operandType(result));
7082
7083 #if VIEW_SIZE
7084     pic14_emitcode("; shift left ","result %d, left %d",size,
7085              AOP_SIZE(left));
7086 #endif
7087
7088     /* I suppose that the left size >= result size */
7089     if(shCount == 0){
7090         while(size--){
7091             movLeft2Result(left, size, result, size);
7092         }
7093     }
7094
7095     else if(shCount >= (size * 8))
7096         while(size--)
7097             aopPut(AOP(result),zero,size);
7098     else{
7099         switch (size) {
7100             case 1:
7101                 genlshOne (result,left,shCount);
7102                 break;
7103
7104             case 2:
7105             case 3:
7106                 genlshTwo (result,left,shCount);
7107                 break;
7108
7109             case 4:
7110                 genlshFour (result,left,shCount);
7111                 break;
7112         }
7113     }
7114     freeAsmop(left,NULL,ic,TRUE);
7115     freeAsmop(result,NULL,ic,TRUE);
7116 }
7117
7118 /*-----------------------------------------------------------------*
7119  * genMultiAsm - repeat assembly instruction for size of register.
7120  * if endian == 1, then the high byte (i.e base address + size of 
7121  * register) is used first else the low byte is used first;
7122  *-----------------------------------------------------------------*/
7123 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7124 {
7125
7126   int offset = 0;
7127
7128   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7129
7130   if(!reg)
7131     return;
7132
7133   if(!endian) {
7134     endian = 1;
7135   } else {
7136     endian = -1;
7137     offset = size-1;
7138   }
7139
7140   while(size--) {
7141     emitpcode(poc,    popGet(AOP(reg),offset));
7142     offset += endian;
7143   }
7144
7145 }
7146 /*-----------------------------------------------------------------*/
7147 /* genLeftShift - generates code for left shifting                 */
7148 /*-----------------------------------------------------------------*/
7149 static void genLeftShift (iCode *ic)
7150 {
7151   operand *left,*right, *result;
7152   int size, offset;
7153   char *l;
7154   symbol *tlbl , *tlbl1;
7155   pCodeOp *pctemp;
7156
7157   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7158
7159   right = IC_RIGHT(ic);
7160   left  = IC_LEFT(ic);
7161   result = IC_RESULT(ic);
7162
7163   aopOp(right,ic,FALSE);
7164
7165   /* if the shift count is known then do it 
7166      as efficiently as possible */
7167   if (AOP_TYPE(right) == AOP_LIT) {
7168     genLeftShiftLiteral (left,right,result,ic);
7169     return ;
7170   }
7171
7172   /* shift count is unknown then we have to form 
7173      a loop get the loop count in B : Note: we take
7174      only the lower order byte since shifting
7175      more that 32 bits make no sense anyway, ( the
7176      largest size of an object can be only 32 bits ) */  
7177
7178     
7179   aopOp(left,ic,FALSE);
7180   aopOp(result,ic,FALSE);
7181
7182   /* now move the left to the result if they are not the
7183      same */
7184   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7185       AOP_SIZE(result) > 1) {
7186
7187     size = AOP_SIZE(result);
7188     offset=0;
7189     while (size--) {
7190       l = aopGet(AOP(left),offset,FALSE,TRUE);
7191       if (*l == '@' && (IS_AOP_PREG(result))) {
7192
7193         pic14_emitcode("mov","a,%s",l);
7194         aopPut(AOP(result),"a",offset);
7195       } else {
7196         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7197         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7198         //aopPut(AOP(result),l,offset);
7199       }
7200       offset++;
7201     }
7202   }
7203
7204   size = AOP_SIZE(result);
7205
7206   /* if it is only one byte then */
7207   if (size == 1) {
7208     if(optimized_for_speed) {
7209       emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7210       emitpcode(POC_ANDLW,  popGetLit(0xf0));
7211       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7212       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7213       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7214       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7215       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7216       emitpcode(POC_RLFW,   popGet(AOP(result),0));
7217       emitpcode(POC_ANDLW,  popGetLit(0xfe));
7218       emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7219       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7220       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7221     } else {
7222
7223       tlbl = newiTempLabel(NULL);
7224       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7225         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7226         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7227       }
7228
7229       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7230       emitpcode(POC_RRF,    popGet(AOP(result),0));
7231       emitpLabel(tlbl->key);
7232       emitpcode(POC_RLF,    popGet(AOP(result),0));
7233       emitpcode(POC_ADDLW,  popGetLit(1));
7234       emitSKPC;
7235       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7236     }
7237     goto release ;
7238   }
7239     
7240   if (pic14_sameRegs(AOP(left),AOP(result))) {
7241
7242     tlbl = newiTempLabel(NULL);
7243     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7244     genMultiAsm(POC_RRF, result, size,1);
7245     emitpLabel(tlbl->key);
7246     genMultiAsm(POC_RLF, result, size,0);
7247     emitpcode(POC_ADDLW,  popGetLit(1));
7248     emitSKPC;
7249     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7250     goto release;
7251   }
7252
7253   //tlbl = newiTempLabel(NULL);
7254   //offset = 0 ;   
7255   //tlbl1 = newiTempLabel(NULL);
7256
7257   //reAdjustPreg(AOP(result));    
7258     
7259   //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7260   //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7261   //l = aopGet(AOP(result),offset,FALSE,FALSE);
7262   //MOVA(l);
7263   //pic14_emitcode("add","a,acc");         
7264   //aopPut(AOP(result),"a",offset++);
7265   //while (--size) {
7266   //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7267   //  MOVA(l);
7268   //  pic14_emitcode("rlc","a");         
7269   //  aopPut(AOP(result),"a",offset++);
7270   //}
7271   //reAdjustPreg(AOP(result));
7272
7273   //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7274   //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7275
7276
7277   tlbl = newiTempLabel(NULL);
7278   tlbl1= newiTempLabel(NULL);
7279
7280   size = AOP_SIZE(result);
7281   offset = 1;
7282
7283   pctemp = popGetTempReg();  /* grab a temporary working register. */
7284
7285   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7286
7287   /* offset should be 0, 1 or 3 */
7288   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7289   emitSKPNZ;
7290   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7291
7292   emitpcode(POC_MOVWF, pctemp);
7293
7294
7295   emitpLabel(tlbl->key);
7296
7297   emitCLRC;
7298   emitpcode(POC_RLF,  popGet(AOP(result),0));
7299   while(--size)
7300     emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7301
7302   emitpcode(POC_DECFSZ,  pctemp);
7303   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7304   emitpLabel(tlbl1->key);
7305
7306   popReleaseTempReg(pctemp);
7307
7308
7309  release:
7310   freeAsmop (right,NULL,ic,TRUE);
7311   freeAsmop(left,NULL,ic,TRUE);
7312   freeAsmop(result,NULL,ic,TRUE);
7313 }
7314
7315 /*-----------------------------------------------------------------*/
7316 /* genrshOne - right shift a one byte quantity by known count      */
7317 /*-----------------------------------------------------------------*/
7318 static void genrshOne (operand *result, operand *left,
7319                        int shCount, int sign)
7320 {
7321     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7322     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7323 }
7324
7325 /*-----------------------------------------------------------------*/
7326 /* genrshTwo - right shift two bytes by known amount != 0          */
7327 /*-----------------------------------------------------------------*/
7328 static void genrshTwo (operand *result,operand *left,
7329                        int shCount, int sign)
7330 {
7331   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7332   /* if shCount >= 8 */
7333   if (shCount >= 8) {
7334     shCount -= 8 ;
7335     if (shCount)
7336       shiftR1Left2Result(left, MSB16, result, LSB,
7337                          shCount, sign);
7338     else
7339       movLeft2Result(left, MSB16, result, LSB);
7340
7341     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7342
7343     if(sign) {
7344       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7345       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7346     }
7347   }
7348
7349   /*  1 <= shCount <= 7 */
7350   else
7351     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7352 }
7353
7354 /*-----------------------------------------------------------------*/
7355 /* shiftRLong - shift right one long from left to result           */
7356 /* offl = LSB or MSB16                                             */
7357 /*-----------------------------------------------------------------*/
7358 static void shiftRLong (operand *left, int offl,
7359                         operand *result, int sign)
7360 {
7361     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7362     if(!sign)
7363         pic14_emitcode("clr","c");
7364     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7365     if(sign)
7366         pic14_emitcode("mov","c,acc.7");
7367     pic14_emitcode("rrc","a");
7368     aopPut(AOP(result),"a",MSB32-offl);
7369     if(offl == MSB16)
7370         /* add sign of "a" */
7371         addSign(result, MSB32, sign);
7372
7373     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7374     pic14_emitcode("rrc","a");
7375     aopPut(AOP(result),"a",MSB24-offl);
7376
7377     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7378     pic14_emitcode("rrc","a");
7379     aopPut(AOP(result),"a",MSB16-offl);
7380
7381     if(offl == LSB){
7382         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7383         pic14_emitcode("rrc","a");
7384         aopPut(AOP(result),"a",LSB);
7385     }
7386 }
7387
7388 /*-----------------------------------------------------------------*/
7389 /* genrshFour - shift four byte by a known amount != 0             */
7390 /*-----------------------------------------------------------------*/
7391 static void genrshFour (operand *result, operand *left,
7392                         int shCount, int sign)
7393 {
7394   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7395   /* if shifting more that 3 bytes */
7396   if(shCount >= 24 ) {
7397     shCount -= 24;
7398     if(shCount)
7399       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7400     else
7401       movLeft2Result(left, MSB32, result, LSB);
7402
7403     addSign(result, MSB16, sign);
7404   }
7405   else if(shCount >= 16){
7406     shCount -= 16;
7407     if(shCount)
7408       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7409     else{
7410       movLeft2Result(left, MSB24, result, LSB);
7411       movLeft2Result(left, MSB32, result, MSB16);
7412     }
7413     addSign(result, MSB24, sign);
7414   }
7415   else if(shCount >= 8){
7416     shCount -= 8;
7417     if(shCount == 1)
7418       shiftRLong(left, MSB16, result, sign);
7419     else if(shCount == 0){
7420       movLeft2Result(left, MSB16, result, LSB);
7421       movLeft2Result(left, MSB24, result, MSB16);
7422       movLeft2Result(left, MSB32, result, MSB24);
7423       addSign(result, MSB32, sign);
7424     }
7425     else{
7426       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7427       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7428       /* the last shift is signed */
7429       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7430       addSign(result, MSB32, sign);
7431     }
7432   }
7433   else{   /* 1 <= shCount <= 7 */
7434     if(shCount <= 2){
7435       shiftRLong(left, LSB, result, sign);
7436       if(shCount == 2)
7437         shiftRLong(result, LSB, result, sign);
7438     }
7439     else{
7440       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7441       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7442       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7443     }
7444   }
7445 }
7446
7447 /*-----------------------------------------------------------------*/
7448 /* genRightShiftLiteral - right shifting by known count            */
7449 /*-----------------------------------------------------------------*/
7450 static void genRightShiftLiteral (operand *left,
7451                                   operand *right,
7452                                   operand *result,
7453                                   iCode *ic,
7454                                   int sign)
7455 {    
7456   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7457   int lsize,res_size;
7458
7459   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7460   freeAsmop(right,NULL,ic,TRUE);
7461
7462   aopOp(left,ic,FALSE);
7463   aopOp(result,ic,FALSE);
7464
7465 #if VIEW_SIZE
7466   pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7467                  AOP_SIZE(left));
7468 #endif
7469
7470   lsize = pic14_getDataSize(left);
7471   res_size = pic14_getDataSize(result);
7472   /* test the LEFT size !!! */
7473
7474   /* I suppose that the left size >= result size */
7475   if(shCount == 0){
7476     while(res_size--)
7477       movLeft2Result(left, lsize, result, res_size);
7478   }
7479
7480   else if(shCount >= (lsize * 8)){
7481
7482     if(res_size == 1) {
7483       emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7484       if(sign) {
7485         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7486         emitpcode(POC_DECF, popGet(AOP(result),LSB));
7487       }
7488     } else {
7489
7490       if(sign) {
7491         emitpcode(POC_MOVLW, popGetLit(0));
7492         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7493         emitpcode(POC_MOVLW, popGetLit(0xff));
7494         while(res_size--)
7495           emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7496
7497       } else {
7498
7499         while(res_size--)
7500           emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7501       }
7502     }
7503   } else {
7504
7505     switch (res_size) {
7506     case 1:
7507       genrshOne (result,left,shCount,sign);
7508       break;
7509
7510     case 2:
7511       genrshTwo (result,left,shCount,sign);
7512       break;
7513
7514     case 4:
7515       genrshFour (result,left,shCount,sign);
7516       break;
7517     default :
7518       break;
7519     }
7520
7521   }
7522
7523   freeAsmop(left,NULL,ic,TRUE);
7524   freeAsmop(result,NULL,ic,TRUE);
7525 }
7526
7527 /*-----------------------------------------------------------------*/
7528 /* genSignedRightShift - right shift of signed number              */
7529 /*-----------------------------------------------------------------*/
7530 static void genSignedRightShift (iCode *ic)
7531 {
7532   operand *right, *left, *result;
7533   int size, offset;
7534   //  char *l;
7535   symbol *tlbl, *tlbl1 ;
7536   pCodeOp *pctemp;
7537
7538   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7539
7540   /* we do it the hard way put the shift count in b
7541      and loop thru preserving the sign */
7542   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7543
7544   right = IC_RIGHT(ic);
7545   left  = IC_LEFT(ic);
7546   result = IC_RESULT(ic);
7547
7548   aopOp(right,ic,FALSE);  
7549   aopOp(left,ic,FALSE);
7550   aopOp(result,ic,FALSE);
7551
7552
7553   if ( AOP_TYPE(right) == AOP_LIT) {
7554     genRightShiftLiteral (left,right,result,ic,1);
7555     return ;
7556   }
7557   /* shift count is unknown then we have to form 
7558      a loop get the loop count in B : Note: we take
7559      only the lower order byte since shifting
7560      more that 32 bits make no sense anyway, ( the
7561      largest size of an object can be only 32 bits ) */  
7562
7563   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7564   //pic14_emitcode("inc","b");
7565   //freeAsmop (right,NULL,ic,TRUE);
7566   //aopOp(left,ic,FALSE);
7567   //aopOp(result,ic,FALSE);
7568
7569   /* now move the left to the result if they are not the
7570      same */
7571   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7572       AOP_SIZE(result) > 1) {
7573
7574     size = AOP_SIZE(result);
7575     offset=0;
7576     while (size--) { 
7577       /*
7578         l = aopGet(AOP(left),offset,FALSE,TRUE);
7579         if (*l == '@' && IS_AOP_PREG(result)) {
7580
7581         pic14_emitcode("mov","a,%s",l);
7582         aopPut(AOP(result),"a",offset);
7583         } else
7584         aopPut(AOP(result),l,offset);
7585       */
7586       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7587       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7588
7589       offset++;
7590     }
7591   }
7592
7593   /* mov the highest order bit to OVR */    
7594   tlbl = newiTempLabel(NULL);
7595   tlbl1= newiTempLabel(NULL);
7596
7597   size = AOP_SIZE(result);
7598   offset = size - 1;
7599
7600   pctemp = popGetTempReg();  /* grab a temporary working register. */
7601
7602   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7603
7604   /* offset should be 0, 1 or 3 */
7605   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7606   emitSKPNZ;
7607   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7608
7609   emitpcode(POC_MOVWF, pctemp);
7610
7611
7612   emitpLabel(tlbl->key);
7613
7614   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7615   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7616
7617   while(--size) {
7618     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7619   }
7620
7621   emitpcode(POC_DECFSZ,  pctemp);
7622   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7623   emitpLabel(tlbl1->key);
7624
7625   popReleaseTempReg(pctemp);
7626 #if 0
7627   size = AOP_SIZE(result);
7628   offset = size - 1;
7629   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7630   pic14_emitcode("rlc","a");
7631   pic14_emitcode("mov","ov,c");
7632   /* if it is only one byte then */
7633   if (size == 1) {
7634     l = aopGet(AOP(left),0,FALSE,FALSE);
7635     MOVA(l);
7636     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7637     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7638     pic14_emitcode("mov","c,ov");
7639     pic14_emitcode("rrc","a");
7640     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7641     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7642     aopPut(AOP(result),"a",0);
7643     goto release ;
7644   }
7645
7646   reAdjustPreg(AOP(result));
7647   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7648   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7649   pic14_emitcode("mov","c,ov");
7650   while (size--) {
7651     l = aopGet(AOP(result),offset,FALSE,FALSE);
7652     MOVA(l);
7653     pic14_emitcode("rrc","a");         
7654     aopPut(AOP(result),"a",offset--);
7655   }
7656   reAdjustPreg(AOP(result));
7657   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7658   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7659
7660  release:
7661 #endif
7662
7663   freeAsmop(left,NULL,ic,TRUE);
7664   freeAsmop(result,NULL,ic,TRUE);
7665   freeAsmop(right,NULL,ic,TRUE);
7666 }
7667
7668 /*-----------------------------------------------------------------*/
7669 /* genRightShift - generate code for right shifting                */
7670 /*-----------------------------------------------------------------*/
7671 static void genRightShift (iCode *ic)
7672 {
7673     operand *right, *left, *result;
7674     sym_link *retype ;
7675     int size, offset;
7676     char *l;
7677     symbol *tlbl, *tlbl1 ;
7678
7679     /* if signed then we do it the hard way preserve the
7680     sign bit moving it inwards */
7681     retype = getSpec(operandType(IC_RESULT(ic)));
7682     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7683
7684     if (!SPEC_USIGN(retype)) {
7685         genSignedRightShift (ic);
7686         return ;
7687     }
7688
7689     /* signed & unsigned types are treated the same : i.e. the
7690     signed is NOT propagated inwards : quoting from the
7691     ANSI - standard : "for E1 >> E2, is equivalent to division
7692     by 2**E2 if unsigned or if it has a non-negative value,
7693     otherwise the result is implementation defined ", MY definition
7694     is that the sign does not get propagated */
7695
7696     right = IC_RIGHT(ic);
7697     left  = IC_LEFT(ic);
7698     result = IC_RESULT(ic);
7699
7700     aopOp(right,ic,FALSE);
7701
7702     /* if the shift count is known then do it 
7703     as efficiently as possible */
7704     if (AOP_TYPE(right) == AOP_LIT) {
7705         genRightShiftLiteral (left,right,result,ic, 0);
7706         return ;
7707     }
7708
7709     /* shift count is unknown then we have to form 
7710     a loop get the loop count in B : Note: we take
7711     only the lower order byte since shifting
7712     more that 32 bits make no sense anyway, ( the
7713     largest size of an object can be only 32 bits ) */  
7714
7715     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7716     pic14_emitcode("inc","b");
7717     aopOp(left,ic,FALSE);
7718     aopOp(result,ic,FALSE);
7719
7720     /* now move the left to the result if they are not the
7721     same */
7722     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7723         AOP_SIZE(result) > 1) {
7724
7725         size = AOP_SIZE(result);
7726         offset=0;
7727         while (size--) {
7728             l = aopGet(AOP(left),offset,FALSE,TRUE);
7729             if (*l == '@' && IS_AOP_PREG(result)) {
7730
7731                 pic14_emitcode("mov","a,%s",l);
7732                 aopPut(AOP(result),"a",offset);
7733             } else
7734                 aopPut(AOP(result),l,offset);
7735             offset++;
7736         }
7737     }
7738
7739     tlbl = newiTempLabel(NULL);
7740     tlbl1= newiTempLabel(NULL);
7741     size = AOP_SIZE(result);
7742     offset = size - 1;
7743
7744     /* if it is only one byte then */
7745     if (size == 1) {
7746
7747       tlbl = newiTempLabel(NULL);
7748       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7749         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7750         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7751       }
7752
7753       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7754       emitpcode(POC_RLF,    popGet(AOP(result),0));
7755       emitpLabel(tlbl->key);
7756       emitpcode(POC_RRF,    popGet(AOP(result),0));
7757       emitpcode(POC_ADDLW,  popGetLit(1));
7758       emitSKPC;
7759       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7760
7761       goto release ;
7762     }
7763
7764     reAdjustPreg(AOP(result));
7765     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7766     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7767     CLRC;
7768     while (size--) {
7769         l = aopGet(AOP(result),offset,FALSE,FALSE);
7770         MOVA(l);
7771         pic14_emitcode("rrc","a");         
7772         aopPut(AOP(result),"a",offset--);
7773     }
7774     reAdjustPreg(AOP(result));
7775
7776     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7777     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7778
7779 release:
7780     freeAsmop(left,NULL,ic,TRUE);
7781     freeAsmop (right,NULL,ic,TRUE);
7782     freeAsmop(result,NULL,ic,TRUE);
7783 }
7784
7785 /*-----------------------------------------------------------------*/
7786 /* genUnpackBits - generates code for unpacking bits               */
7787 /*-----------------------------------------------------------------*/
7788 static void genUnpackBits (operand *result, char *rname, int ptype)
7789 {    
7790     int shCnt ;
7791     int rlen = 0 ;
7792     sym_link *etype;
7793     int offset = 0 ;
7794
7795     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7796     etype = getSpec(operandType(result));
7797
7798     /* read the first byte  */
7799     switch (ptype) {
7800
7801     case POINTER:
7802     case IPOINTER:
7803         pic14_emitcode("mov","a,@%s",rname);
7804         break;
7805         
7806     case PPOINTER:
7807         pic14_emitcode("movx","a,@%s",rname);
7808         break;
7809         
7810     case FPOINTER:
7811         pic14_emitcode("movx","a,@dptr");
7812         break;
7813
7814     case CPOINTER:
7815         pic14_emitcode("clr","a");
7816         pic14_emitcode("movc","a","@a+dptr");
7817         break;
7818
7819     case GPOINTER:
7820         pic14_emitcode("lcall","__gptrget");
7821         break;
7822     }
7823
7824     /* if we have bitdisplacement then it fits   */
7825     /* into this byte completely or if length is */
7826     /* less than a byte                          */
7827     if ((shCnt = SPEC_BSTR(etype)) || 
7828         (SPEC_BLEN(etype) <= 8))  {
7829
7830         /* shift right acc */
7831         AccRsh(shCnt);
7832
7833         pic14_emitcode("anl","a,#0x%02x",
7834                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7835         aopPut(AOP(result),"a",offset);
7836         return ;
7837     }
7838
7839     /* bit field did not fit in a byte  */
7840     rlen = SPEC_BLEN(etype) - 8;
7841     aopPut(AOP(result),"a",offset++);
7842
7843     while (1)  {
7844
7845         switch (ptype) {
7846         case POINTER:
7847         case IPOINTER:
7848             pic14_emitcode("inc","%s",rname);
7849             pic14_emitcode("mov","a,@%s",rname);
7850             break;
7851             
7852         case PPOINTER:
7853             pic14_emitcode("inc","%s",rname);
7854             pic14_emitcode("movx","a,@%s",rname);
7855             break;
7856
7857         case FPOINTER:
7858             pic14_emitcode("inc","dptr");
7859             pic14_emitcode("movx","a,@dptr");
7860             break;
7861             
7862         case CPOINTER:
7863             pic14_emitcode("clr","a");
7864             pic14_emitcode("inc","dptr");
7865             pic14_emitcode("movc","a","@a+dptr");
7866             break;
7867             
7868         case GPOINTER:
7869             pic14_emitcode("inc","dptr");
7870             pic14_emitcode("lcall","__gptrget");
7871             break;
7872         }
7873
7874         rlen -= 8;            
7875         /* if we are done */
7876         if ( rlen <= 0 )
7877             break ;
7878         
7879         aopPut(AOP(result),"a",offset++);
7880                               
7881     }
7882     
7883     if (rlen) {
7884         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7885         aopPut(AOP(result),"a",offset);        
7886     }
7887     
7888     return ;
7889 }
7890
7891 #if 0
7892 /*-----------------------------------------------------------------*/
7893 /* genDataPointerGet - generates code when ptr offset is known     */
7894 /*-----------------------------------------------------------------*/
7895 static void genDataPointerGet (operand *left, 
7896                                operand *result, 
7897                                iCode *ic)
7898 {
7899   int size , offset = 0;
7900
7901
7902   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7903
7904
7905   /* optimization - most of the time, left and result are the same
7906    * address, but different types. for the pic code, we could omit
7907    * the following
7908    */
7909
7910   aopOp(result,ic,TRUE);
7911
7912   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7913
7914   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7915
7916   size = AOP_SIZE(result);
7917
7918   while (size--) {
7919     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7920     offset++;
7921   }
7922
7923   freeAsmop(left,NULL,ic,TRUE);
7924   freeAsmop(result,NULL,ic,TRUE);
7925 }
7926 #endif
7927 /*-----------------------------------------------------------------*/
7928 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7929 /*-----------------------------------------------------------------*/
7930 static void genNearPointerGet (operand *left, 
7931                                operand *result, 
7932                                iCode *ic)
7933 {
7934     asmop *aop = NULL;
7935     //regs *preg = NULL ;
7936     char *rname ;
7937     sym_link *rtype, *retype;
7938     sym_link *ltype = operandType(left);    
7939     //char buffer[80];
7940
7941     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7942
7943     rtype = operandType(result);
7944     retype= getSpec(rtype);
7945     
7946     aopOp(left,ic,FALSE);
7947     
7948     /* if left is rematerialisable and
7949        result is not bit variable type and
7950        the left is pointer to data space i.e
7951        lower 128 bytes of space */
7952     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
7953         !IS_BITVAR(retype)         &&
7954         DCL_TYPE(ltype) == POINTER) {
7955       //genDataPointerGet (left,result,ic);
7956         return ;
7957     }
7958     
7959     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7960
7961         /* if the value is already in a pointer register
7962        then don't need anything more */
7963     if (!AOP_INPREG(AOP(left))) {
7964         /* otherwise get a free pointer register */
7965     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7966 /*
7967         aop = newAsmop(0);
7968         preg = getFreePtr(ic,&aop,FALSE);
7969         pic14_emitcode("mov","%s,%s",
7970                 preg->name,
7971                 aopGet(AOP(left),0,FALSE,TRUE));
7972         rname = preg->name ;
7973 */
7974     rname ="BAD";
7975     } else
7976         rname = aopGet(AOP(left),0,FALSE,FALSE);
7977     
7978     aopOp (result,ic,FALSE);
7979     
7980       /* if bitfield then unpack the bits */
7981     if (IS_BITVAR(retype)) 
7982         genUnpackBits (result,rname,POINTER);
7983     else {
7984         /* we have can just get the values */
7985       int size = AOP_SIZE(result);
7986       int offset = 0 ;  
7987         
7988       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7989
7990       emitpcode(POC_MOVFW,popGet(AOP(left),0));
7991       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7992       while(size--) {
7993         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7994         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7995         if(size)
7996           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7997       }
7998 /*
7999         while (size--) {
8000             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8001
8002                 pic14_emitcode("mov","a,@%s",rname);
8003                 aopPut(AOP(result),"a",offset);
8004             } else {
8005                 sprintf(buffer,"@%s",rname);
8006                 aopPut(AOP(result),buffer,offset);
8007             }
8008             offset++ ;
8009             if (size)
8010                 pic14_emitcode("inc","%s",rname);
8011         }
8012 */
8013     }
8014
8015     /* now some housekeeping stuff */
8016     if (aop) {
8017         /* we had to allocate for this iCode */
8018     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8019         freeAsmop(NULL,aop,ic,TRUE);
8020     } else { 
8021         /* we did not allocate which means left
8022            already in a pointer register, then
8023            if size > 0 && this could be used again
8024            we have to point it back to where it 
8025            belongs */
8026     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8027         if (AOP_SIZE(result) > 1 &&
8028             !OP_SYMBOL(left)->remat &&
8029             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8030               ic->depth )) {
8031             int size = AOP_SIZE(result) - 1;
8032             while (size--)
8033                 pic14_emitcode("dec","%s",rname);
8034         }
8035     }
8036
8037     /* done */
8038     freeAsmop(left,NULL,ic,TRUE);
8039     freeAsmop(result,NULL,ic,TRUE);
8040      
8041 }
8042
8043 /*-----------------------------------------------------------------*/
8044 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8045 /*-----------------------------------------------------------------*/
8046 static void genPagedPointerGet (operand *left, 
8047                                operand *result, 
8048                                iCode *ic)
8049 {
8050     asmop *aop = NULL;
8051     regs *preg = NULL ;
8052     char *rname ;
8053     sym_link *rtype, *retype;    
8054
8055     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8056
8057     rtype = operandType(result);
8058     retype= getSpec(rtype);
8059     
8060     aopOp(left,ic,FALSE);
8061
8062   /* if the value is already in a pointer register
8063        then don't need anything more */
8064     if (!AOP_INPREG(AOP(left))) {
8065         /* otherwise get a free pointer register */
8066         aop = newAsmop(0);
8067         preg = getFreePtr(ic,&aop,FALSE);
8068         pic14_emitcode("mov","%s,%s",
8069                 preg->name,
8070                 aopGet(AOP(left),0,FALSE,TRUE));
8071         rname = preg->name ;
8072     } else
8073         rname = aopGet(AOP(left),0,FALSE,FALSE);
8074     
8075     freeAsmop(left,NULL,ic,TRUE);
8076     aopOp (result,ic,FALSE);
8077
8078     /* if bitfield then unpack the bits */
8079     if (IS_BITVAR(retype)) 
8080         genUnpackBits (result,rname,PPOINTER);
8081     else {
8082         /* we have can just get the values */
8083         int size = AOP_SIZE(result);
8084         int offset = 0 ;        
8085         
8086         while (size--) {
8087             
8088             pic14_emitcode("movx","a,@%s",rname);
8089             aopPut(AOP(result),"a",offset);
8090             
8091             offset++ ;
8092             
8093             if (size)
8094                 pic14_emitcode("inc","%s",rname);
8095         }
8096     }
8097
8098     /* now some housekeeping stuff */
8099     if (aop) {
8100         /* we had to allocate for this iCode */
8101         freeAsmop(NULL,aop,ic,TRUE);
8102     } else { 
8103         /* we did not allocate which means left
8104            already in a pointer register, then
8105            if size > 0 && this could be used again
8106            we have to point it back to where it 
8107            belongs */
8108         if (AOP_SIZE(result) > 1 &&
8109             !OP_SYMBOL(left)->remat &&
8110             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8111               ic->depth )) {
8112             int size = AOP_SIZE(result) - 1;
8113             while (size--)
8114                 pic14_emitcode("dec","%s",rname);
8115         }
8116     }
8117
8118     /* done */
8119     freeAsmop(result,NULL,ic,TRUE);
8120     
8121         
8122 }
8123
8124 /*-----------------------------------------------------------------*/
8125 /* genFarPointerGet - gget value from far space                    */
8126 /*-----------------------------------------------------------------*/
8127 static void genFarPointerGet (operand *left,
8128                               operand *result, iCode *ic)
8129 {
8130     int size, offset ;
8131     sym_link *retype = getSpec(operandType(result));
8132
8133     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8134
8135     aopOp(left,ic,FALSE);
8136
8137     /* if the operand is already in dptr 
8138     then we do nothing else we move the value to dptr */
8139     if (AOP_TYPE(left) != AOP_STR) {
8140         /* if this is remateriazable */
8141         if (AOP_TYPE(left) == AOP_IMMD)
8142             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8143         else { /* we need to get it byte by byte */
8144             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8145             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8146             if (options.model == MODEL_FLAT24)
8147             {
8148                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8149             }
8150         }
8151     }
8152     /* so dptr know contains the address */
8153     freeAsmop(left,NULL,ic,TRUE);
8154     aopOp(result,ic,FALSE);
8155
8156     /* if bit then unpack */
8157     if (IS_BITVAR(retype)) 
8158         genUnpackBits(result,"dptr",FPOINTER);
8159     else {
8160         size = AOP_SIZE(result);
8161         offset = 0 ;
8162
8163         while (size--) {
8164             pic14_emitcode("movx","a,@dptr");
8165             aopPut(AOP(result),"a",offset++);
8166             if (size)
8167                 pic14_emitcode("inc","dptr");
8168         }
8169     }
8170
8171     freeAsmop(result,NULL,ic,TRUE);
8172 }
8173 #if 0
8174 /*-----------------------------------------------------------------*/
8175 /* genCodePointerGet - get value from code space                  */
8176 /*-----------------------------------------------------------------*/
8177 static void genCodePointerGet (operand *left,
8178                                 operand *result, iCode *ic)
8179 {
8180     int size, offset ;
8181     sym_link *retype = getSpec(operandType(result));
8182
8183     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8184
8185     aopOp(left,ic,FALSE);
8186
8187     /* if the operand is already in dptr 
8188     then we do nothing else we move the value to dptr */
8189     if (AOP_TYPE(left) != AOP_STR) {
8190         /* if this is remateriazable */
8191         if (AOP_TYPE(left) == AOP_IMMD)
8192             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8193         else { /* we need to get it byte by byte */
8194             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8195             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8196             if (options.model == MODEL_FLAT24)
8197             {
8198                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8199             }
8200         }
8201     }
8202     /* so dptr know contains the address */
8203     freeAsmop(left,NULL,ic,TRUE);
8204     aopOp(result,ic,FALSE);
8205
8206     /* if bit then unpack */
8207     if (IS_BITVAR(retype)) 
8208         genUnpackBits(result,"dptr",CPOINTER);
8209     else {
8210         size = AOP_SIZE(result);
8211         offset = 0 ;
8212
8213         while (size--) {
8214             pic14_emitcode("clr","a");
8215             pic14_emitcode("movc","a,@a+dptr");
8216             aopPut(AOP(result),"a",offset++);
8217             if (size)
8218                 pic14_emitcode("inc","dptr");
8219         }
8220     }
8221
8222     freeAsmop(result,NULL,ic,TRUE);
8223 }
8224 #endif
8225 /*-----------------------------------------------------------------*/
8226 /* genGenPointerGet - gget value from generic pointer space        */
8227 /*-----------------------------------------------------------------*/
8228 static void genGenPointerGet (operand *left,
8229                               operand *result, iCode *ic)
8230 {
8231   int size, offset ;
8232   sym_link *retype = getSpec(operandType(result));
8233
8234   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8235   aopOp(left,ic,FALSE);
8236   aopOp(result,ic,FALSE);
8237
8238
8239   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8240
8241   /* if the operand is already in dptr 
8242      then we do nothing else we move the value to dptr */
8243   //  if (AOP_TYPE(left) != AOP_STR) {
8244     /* if this is remateriazable */
8245     if (AOP_TYPE(left) == AOP_IMMD) {
8246       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8247       pic14_emitcode("mov","b,#%d",pointerCode(retype));
8248     }
8249     else { /* we need to get it byte by byte */
8250
8251       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8252       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8253
8254       size = AOP_SIZE(result);
8255       offset = 0 ;
8256
8257       while(size--) {
8258         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8259         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8260         if(size)
8261           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8262       }
8263       goto release;
8264     }
8265     //}
8266   /* so dptr know contains the address */
8267
8268   /* if bit then unpack */
8269   //if (IS_BITVAR(retype)) 
8270   //  genUnpackBits(result,"dptr",GPOINTER);
8271
8272  release:
8273   freeAsmop(left,NULL,ic,TRUE);
8274   freeAsmop(result,NULL,ic,TRUE);
8275
8276 }
8277
8278 /*-----------------------------------------------------------------*/
8279 /* genConstPointerGet - get value from const generic pointer space */
8280 /*-----------------------------------------------------------------*/
8281 static void genConstPointerGet (operand *left,
8282                                 operand *result, iCode *ic)
8283 {
8284   //sym_link *retype = getSpec(operandType(result));
8285   symbol *albl = newiTempLabel(NULL);
8286   symbol *blbl = newiTempLabel(NULL);
8287   PIC_OPCODE poc;
8288   pCodeOp *pcop;
8289
8290   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8291   aopOp(left,ic,FALSE);
8292   aopOp(result,ic,FALSE);
8293
8294
8295   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8296
8297   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8298
8299   emitpcode(POC_CALL,popGetLabel(albl->key));
8300   pcop = popGetLabel(blbl->key);
8301   emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8302   emitpcode(POC_GOTO,pcop);
8303   emitpLabel(albl->key);
8304
8305   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8306     
8307   emitpcode(poc,popGet(AOP(left),1));
8308   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8309   emitpcode(poc,popGet(AOP(left),0));
8310   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8311
8312   emitpLabel(blbl->key);
8313
8314   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8315
8316
8317   freeAsmop(left,NULL,ic,TRUE);
8318   freeAsmop(result,NULL,ic,TRUE);
8319
8320 }
8321 /*-----------------------------------------------------------------*/
8322 /* genPointerGet - generate code for pointer get                   */
8323 /*-----------------------------------------------------------------*/
8324 static void genPointerGet (iCode *ic)
8325 {
8326     operand *left, *result ;
8327     sym_link *type, *etype;
8328     int p_type;
8329
8330     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8331
8332     left = IC_LEFT(ic);
8333     result = IC_RESULT(ic) ;
8334
8335     /* depending on the type of pointer we need to
8336     move it to the correct pointer register */
8337     type = operandType(left);
8338     etype = getSpec(type);
8339
8340     if (IS_PTR_CONST(type))
8341       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8342
8343     /* if left is of type of pointer then it is simple */
8344     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8345         p_type = DCL_TYPE(type);
8346     else {
8347         /* we have to go by the storage class */
8348         p_type = PTR_TYPE(SPEC_OCLS(etype));
8349
8350         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8351
8352         if (SPEC_OCLS(etype)->codesp ) {
8353           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8354           //p_type = CPOINTER ; 
8355         }
8356         else
8357             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8358               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8359                /*p_type = FPOINTER ;*/ 
8360             else
8361                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8362                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8363 /*                  p_type = PPOINTER; */
8364                 else
8365                     if (SPEC_OCLS(etype) == idata )
8366                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8367 /*                      p_type = IPOINTER; */
8368                     else
8369                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8370 /*                      p_type = POINTER ; */
8371     }
8372
8373     /* now that we have the pointer type we assign
8374     the pointer values */
8375     switch (p_type) {
8376
8377     case POINTER:       
8378     case IPOINTER:
8379         genNearPointerGet (left,result,ic);
8380         break;
8381
8382     case PPOINTER:
8383         genPagedPointerGet(left,result,ic);
8384         break;
8385
8386     case FPOINTER:
8387         genFarPointerGet (left,result,ic);
8388         break;
8389
8390     case CPOINTER:
8391         genConstPointerGet (left,result,ic);
8392         //pic14_emitcodePointerGet (left,result,ic);
8393         break;
8394
8395     case GPOINTER:
8396       if (IS_PTR_CONST(type))
8397         genConstPointerGet (left,result,ic);
8398       else
8399         genGenPointerGet (left,result,ic);
8400       break;
8401     }
8402
8403 }
8404
8405 /*-----------------------------------------------------------------*/
8406 /* genPackBits - generates code for packed bit storage             */
8407 /*-----------------------------------------------------------------*/
8408 static void genPackBits (sym_link    *etype ,
8409                          operand *right ,
8410                          char *rname, int p_type)
8411 {
8412     int shCount = 0 ;
8413     int offset = 0  ;
8414     int rLen = 0 ;
8415     int blen, bstr ;   
8416     char *l ;
8417
8418     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8419     blen = SPEC_BLEN(etype);
8420     bstr = SPEC_BSTR(etype);
8421
8422     l = aopGet(AOP(right),offset++,FALSE,FALSE);
8423     MOVA(l);   
8424
8425     /* if the bit lenth is less than or    */
8426     /* it exactly fits a byte then         */
8427     if (SPEC_BLEN(etype) <= 8 )  {
8428         shCount = SPEC_BSTR(etype) ;
8429
8430         /* shift left acc */
8431         AccLsh(shCount);
8432
8433         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8434
8435
8436             switch (p_type) {
8437                 case POINTER:
8438                     pic14_emitcode ("mov","b,a");
8439                     pic14_emitcode("mov","a,@%s",rname);
8440                     break;
8441
8442                 case FPOINTER:
8443                     pic14_emitcode ("mov","b,a");
8444                     pic14_emitcode("movx","a,@dptr");
8445                     break;
8446
8447                 case GPOINTER:
8448                     pic14_emitcode ("push","b");
8449                     pic14_emitcode ("push","acc");
8450                     pic14_emitcode ("lcall","__gptrget");
8451                     pic14_emitcode ("pop","b");
8452                     break;
8453             }
8454
8455             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8456                       ((unsigned char)(0xFF << (blen+bstr)) | 
8457                        (unsigned char)(0xFF >> (8-bstr)) ) );
8458             pic14_emitcode ("orl","a,b");
8459             if (p_type == GPOINTER)
8460                 pic14_emitcode("pop","b");
8461         }
8462     }
8463
8464     switch (p_type) {
8465         case POINTER:
8466             pic14_emitcode("mov","@%s,a",rname);
8467             break;
8468
8469         case FPOINTER:
8470             pic14_emitcode("movx","@dptr,a");
8471             break;
8472
8473         case GPOINTER:
8474             DEBUGpic14_emitcode(";lcall","__gptrput");
8475             break;
8476     }
8477
8478     /* if we r done */
8479     if ( SPEC_BLEN(etype) <= 8 )
8480         return ;
8481
8482     pic14_emitcode("inc","%s",rname);
8483     rLen = SPEC_BLEN(etype) ;     
8484
8485     /* now generate for lengths greater than one byte */
8486     while (1) {
8487
8488         l = aopGet(AOP(right),offset++,FALSE,TRUE);
8489
8490         rLen -= 8 ;
8491         if (rLen <= 0 )
8492             break ;
8493
8494         switch (p_type) {
8495             case POINTER:
8496                 if (*l == '@') {
8497                     MOVA(l);
8498                     pic14_emitcode("mov","@%s,a",rname);
8499                 } else
8500                     pic14_emitcode("mov","@%s,%s",rname,l);
8501                 break;
8502
8503             case FPOINTER:
8504                 MOVA(l);
8505                 pic14_emitcode("movx","@dptr,a");
8506                 break;
8507
8508             case GPOINTER:
8509                 MOVA(l);
8510                 DEBUGpic14_emitcode(";lcall","__gptrput");
8511                 break;  
8512         }   
8513         pic14_emitcode ("inc","%s",rname);
8514     }
8515
8516     MOVA(l);
8517
8518     /* last last was not complete */
8519     if (rLen)   {
8520         /* save the byte & read byte */
8521         switch (p_type) {
8522             case POINTER:
8523                 pic14_emitcode ("mov","b,a");
8524                 pic14_emitcode("mov","a,@%s",rname);
8525                 break;
8526
8527             case FPOINTER:
8528                 pic14_emitcode ("mov","b,a");
8529                 pic14_emitcode("movx","a,@dptr");
8530                 break;
8531
8532             case GPOINTER:
8533                 pic14_emitcode ("push","b");
8534                 pic14_emitcode ("push","acc");
8535                 pic14_emitcode ("lcall","__gptrget");
8536                 pic14_emitcode ("pop","b");
8537                 break;
8538         }
8539
8540         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8541         pic14_emitcode ("orl","a,b");
8542     }
8543
8544     if (p_type == GPOINTER)
8545         pic14_emitcode("pop","b");
8546
8547     switch (p_type) {
8548
8549     case POINTER:
8550         pic14_emitcode("mov","@%s,a",rname);
8551         break;
8552         
8553     case FPOINTER:
8554         pic14_emitcode("movx","@dptr,a");
8555         break;
8556         
8557     case GPOINTER:
8558         DEBUGpic14_emitcode(";lcall","__gptrput");
8559         break;                  
8560     }
8561 }
8562 /*-----------------------------------------------------------------*/
8563 /* genDataPointerSet - remat pointer to data space                 */
8564 /*-----------------------------------------------------------------*/
8565 static void genDataPointerSet(operand *right,
8566                               operand *result,
8567                               iCode *ic)
8568 {
8569     int size, offset = 0 ;
8570     char *l, buffer[256];
8571
8572     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8573     aopOp(right,ic,FALSE);
8574     
8575     l = aopGet(AOP(result),0,FALSE,TRUE);
8576     size = AOP_SIZE(right);
8577 /*
8578     if ( AOP_TYPE(result) == AOP_PCODE) {
8579       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8580               AOP(result)->aopu.pcop->name,
8581               PCOI(AOP(result)->aopu.pcop)->offset);
8582     }
8583 */
8584
8585     // tsd, was l+1 - the underline `_' prefix was being stripped
8586     while (size--) {
8587       if (offset) {
8588         sprintf(buffer,"(%s + %d)",l,offset);
8589         fprintf(stderr,"oops  %s\n",buffer);
8590       } else
8591         sprintf(buffer,"%s",l);
8592
8593         if (AOP_TYPE(right) == AOP_LIT) {
8594           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8595           lit = lit >> (8*offset);
8596           if(lit&0xff) {
8597             pic14_emitcode("movlw","%d",lit);
8598             pic14_emitcode("movwf","%s",buffer);
8599
8600             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8601             //emitpcode(POC_MOVWF, popRegFromString(buffer));
8602             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8603
8604           } else {
8605             pic14_emitcode("clrf","%s",buffer);
8606             //emitpcode(POC_CLRF, popRegFromString(buffer));
8607             emitpcode(POC_CLRF, popGet(AOP(result),0));
8608           }
8609         }else {
8610           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8611           pic14_emitcode("movwf","%s",buffer);
8612
8613           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8614           //emitpcode(POC_MOVWF, popRegFromString(buffer));
8615           emitpcode(POC_MOVWF, popGet(AOP(result),0));
8616
8617         }
8618
8619         offset++;
8620     }
8621
8622     freeAsmop(right,NULL,ic,TRUE);
8623     freeAsmop(result,NULL,ic,TRUE);
8624 }
8625
8626 /*-----------------------------------------------------------------*/
8627 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8628 /*-----------------------------------------------------------------*/
8629 static void genNearPointerSet (operand *right,
8630                                operand *result, 
8631                                iCode *ic)
8632 {
8633   asmop *aop = NULL;
8634   char *l;
8635   sym_link *retype;
8636   sym_link *ptype = operandType(result);
8637
8638     
8639   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8640   retype= getSpec(operandType(right));
8641
8642   aopOp(result,ic,FALSE);
8643
8644     
8645   /* if the result is rematerializable &
8646      in data space & not a bit variable */
8647   //if (AOP_TYPE(result) == AOP_IMMD &&
8648   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8649       DCL_TYPE(ptype) == POINTER   &&
8650       !IS_BITVAR(retype)) {
8651     genDataPointerSet (right,result,ic);
8652     freeAsmop(result,NULL,ic,TRUE);
8653     return;
8654   }
8655
8656   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8657   aopOp(right,ic,FALSE);
8658   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8659
8660   /* if the value is already in a pointer register
8661      then don't need anything more */
8662   if (!AOP_INPREG(AOP(result))) {
8663     /* otherwise get a free pointer register */
8664     //aop = newAsmop(0);
8665     //preg = getFreePtr(ic,&aop,FALSE);
8666     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8667     //pic14_emitcode("mov","%s,%s",
8668     //         preg->name,
8669     //         aopGet(AOP(result),0,FALSE,TRUE));
8670     //rname = preg->name ;
8671     //pic14_emitcode("movwf","fsr");
8672     emitpcode(POC_MOVFW, popGet(AOP(result),0));
8673     emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8674     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8675     emitpcode(POC_MOVWF, popCopyReg(&pc_indf));
8676     goto release;
8677
8678   }// else
8679   //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8680
8681
8682   /* if bitfield then unpack the bits */
8683   if (IS_BITVAR(retype)) {
8684     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8685            "The programmer is obviously confused");
8686     //genPackBits (retype,right,rname,POINTER);
8687     exit(1);
8688   }
8689   else {
8690     /* we have can just get the values */
8691     int size = AOP_SIZE(right);
8692     int offset = 0 ;    
8693
8694     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8695     while (size--) {
8696       l = aopGet(AOP(right),offset,FALSE,TRUE);
8697       if (*l == '@' ) {
8698         //MOVA(l);
8699         //pic14_emitcode("mov","@%s,a",rname);
8700         pic14_emitcode("movf","indf,w ;1");
8701       } else {
8702
8703         if (AOP_TYPE(right) == AOP_LIT) {
8704           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8705           if(lit) {
8706             pic14_emitcode("movlw","%s",l);
8707             pic14_emitcode("movwf","indf ;2");
8708           } else 
8709             pic14_emitcode("clrf","indf");
8710         }else {
8711           pic14_emitcode("movf","%s,w",l);
8712           pic14_emitcode("movwf","indf ;2");
8713         }
8714         //pic14_emitcode("mov","@%s,%s",rname,l);
8715       }
8716       if (size)
8717         pic14_emitcode("incf","fsr,f ;3");
8718       //pic14_emitcode("inc","%s",rname);
8719       offset++;
8720     }
8721   }
8722
8723   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8724   /* now some housekeeping stuff */
8725   if (aop) {
8726     /* we had to allocate for this iCode */
8727     freeAsmop(NULL,aop,ic,TRUE);
8728   } else { 
8729     /* we did not allocate which means left
8730        already in a pointer register, then
8731        if size > 0 && this could be used again
8732        we have to point it back to where it 
8733        belongs */
8734     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8735     if (AOP_SIZE(right) > 1 &&
8736         !OP_SYMBOL(result)->remat &&
8737         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8738           ic->depth )) {
8739       int size = AOP_SIZE(right) - 1;
8740       while (size--)
8741         pic14_emitcode("decf","fsr,f");
8742       //pic14_emitcode("dec","%s",rname);
8743     }
8744   }
8745
8746   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8747   /* done */
8748  release:
8749   freeAsmop(right,NULL,ic,TRUE);
8750   freeAsmop(result,NULL,ic,TRUE);
8751 }
8752
8753 /*-----------------------------------------------------------------*/
8754 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8755 /*-----------------------------------------------------------------*/
8756 static void genPagedPointerSet (operand *right,
8757                                operand *result, 
8758                                iCode *ic)
8759 {
8760     asmop *aop = NULL;
8761     regs *preg = NULL ;
8762     char *rname , *l;
8763     sym_link *retype;
8764        
8765     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8766
8767     retype= getSpec(operandType(right));
8768     
8769     aopOp(result,ic,FALSE);
8770     
8771     /* if the value is already in a pointer register
8772        then don't need anything more */
8773     if (!AOP_INPREG(AOP(result))) {
8774         /* otherwise get a free pointer register */
8775         aop = newAsmop(0);
8776         preg = getFreePtr(ic,&aop,FALSE);
8777         pic14_emitcode("mov","%s,%s",
8778                 preg->name,
8779                 aopGet(AOP(result),0,FALSE,TRUE));
8780         rname = preg->name ;
8781     } else
8782         rname = aopGet(AOP(result),0,FALSE,FALSE);
8783     
8784     freeAsmop(result,NULL,ic,TRUE);
8785     aopOp (right,ic,FALSE);
8786
8787     /* if bitfield then unpack the bits */
8788     if (IS_BITVAR(retype)) 
8789         genPackBits (retype,right,rname,PPOINTER);
8790     else {
8791         /* we have can just get the values */
8792         int size = AOP_SIZE(right);
8793         int offset = 0 ;        
8794         
8795         while (size--) {
8796             l = aopGet(AOP(right),offset,FALSE,TRUE);
8797             
8798             MOVA(l);
8799             pic14_emitcode("movx","@%s,a",rname);
8800
8801             if (size)
8802                 pic14_emitcode("inc","%s",rname);
8803
8804             offset++;
8805         }
8806     }
8807     
8808     /* now some housekeeping stuff */
8809     if (aop) {
8810         /* we had to allocate for this iCode */
8811         freeAsmop(NULL,aop,ic,TRUE);
8812     } else { 
8813         /* we did not allocate which means left
8814            already in a pointer register, then
8815            if size > 0 && this could be used again
8816            we have to point it back to where it 
8817            belongs */
8818         if (AOP_SIZE(right) > 1 &&
8819             !OP_SYMBOL(result)->remat &&
8820             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8821               ic->depth )) {
8822             int size = AOP_SIZE(right) - 1;
8823             while (size--)
8824                 pic14_emitcode("dec","%s",rname);
8825         }
8826     }
8827
8828     /* done */
8829     freeAsmop(right,NULL,ic,TRUE);
8830     
8831         
8832 }
8833
8834 /*-----------------------------------------------------------------*/
8835 /* genFarPointerSet - set value from far space                     */
8836 /*-----------------------------------------------------------------*/
8837 static void genFarPointerSet (operand *right,
8838                               operand *result, iCode *ic)
8839 {
8840     int size, offset ;
8841     sym_link *retype = getSpec(operandType(right));
8842
8843     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8844     aopOp(result,ic,FALSE);
8845
8846     /* if the operand is already in dptr 
8847     then we do nothing else we move the value to dptr */
8848     if (AOP_TYPE(result) != AOP_STR) {
8849         /* if this is remateriazable */
8850         if (AOP_TYPE(result) == AOP_IMMD)
8851             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8852         else { /* we need to get it byte by byte */
8853             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8854             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8855             if (options.model == MODEL_FLAT24)
8856             {
8857                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8858             }
8859         }
8860     }
8861     /* so dptr know contains the address */
8862     freeAsmop(result,NULL,ic,TRUE);
8863     aopOp(right,ic,FALSE);
8864
8865     /* if bit then unpack */
8866     if (IS_BITVAR(retype)) 
8867         genPackBits(retype,right,"dptr",FPOINTER);
8868     else {
8869         size = AOP_SIZE(right);
8870         offset = 0 ;
8871
8872         while (size--) {
8873             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8874             MOVA(l);
8875             pic14_emitcode("movx","@dptr,a");
8876             if (size)
8877                 pic14_emitcode("inc","dptr");
8878         }
8879     }
8880
8881     freeAsmop(right,NULL,ic,TRUE);
8882 }
8883
8884 /*-----------------------------------------------------------------*/
8885 /* genGenPointerSet - set value from generic pointer space         */
8886 /*-----------------------------------------------------------------*/
8887 static void genGenPointerSet (operand *right,
8888                               operand *result, iCode *ic)
8889 {
8890   int size, offset ;
8891   sym_link *retype = getSpec(operandType(right));
8892
8893   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8894
8895   aopOp(result,ic,FALSE);
8896   aopOp(right,ic,FALSE);
8897   size = AOP_SIZE(right);
8898
8899   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8900
8901   /* if the operand is already in dptr 
8902      then we do nothing else we move the value to dptr */
8903   if (AOP_TYPE(result) != AOP_STR) {
8904     /* if this is remateriazable */
8905     if (AOP_TYPE(result) == AOP_IMMD) {
8906       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8907       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8908     }
8909     else { /* we need to get it byte by byte */
8910       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8911       size = AOP_SIZE(right);
8912       offset = 0 ;
8913
8914       /* hack hack! see if this the FSR. If so don't load W */
8915       if(AOP_TYPE(right) != AOP_ACC) {
8916
8917
8918         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8919         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8920
8921         if(AOP_SIZE(result) > 1) {
8922           emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8923           emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8924           emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8925
8926         }
8927
8928         //if(size==2)
8929         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8930         //if(size==4) {
8931         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8932         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8933         //}
8934
8935         while(size--) {
8936           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8937           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8938           
8939           if(size)
8940             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8941         }
8942
8943
8944         goto release;
8945       } 
8946
8947       if(aopIdx(AOP(result),0) != 4) {
8948
8949         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8950         goto release;
8951       }
8952
8953       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8954       goto release;
8955
8956     }
8957   }
8958   /* so dptr know contains the address */
8959
8960
8961   /* if bit then unpack */
8962   if (IS_BITVAR(retype)) 
8963     genPackBits(retype,right,"dptr",GPOINTER);
8964   else {
8965     size = AOP_SIZE(right);
8966     offset = 0 ;
8967
8968   DEBUGpic14_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
8969
8970     while (size--) {
8971
8972       emitpcode(POC_MOVFW,popGet(AOP(result),offset));
8973       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8974
8975       if (AOP_TYPE(right) == AOP_LIT) 
8976         emitpcode(POC_MOVLW, popGet(AOP(right),offset));
8977       else
8978         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8979
8980       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8981
8982       offset++;
8983     }
8984   }
8985
8986  release:
8987   freeAsmop(right,NULL,ic,TRUE);
8988   freeAsmop(result,NULL,ic,TRUE);
8989 }
8990
8991 /*-----------------------------------------------------------------*/
8992 /* genPointerSet - stores the value into a pointer location        */
8993 /*-----------------------------------------------------------------*/
8994 static void genPointerSet (iCode *ic)
8995 {    
8996     operand *right, *result ;
8997     sym_link *type, *etype;
8998     int p_type;
8999
9000     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9001
9002     right = IC_RIGHT(ic);
9003     result = IC_RESULT(ic) ;
9004
9005     /* depending on the type of pointer we need to
9006     move it to the correct pointer register */
9007     type = operandType(result);
9008     etype = getSpec(type);
9009     /* if left is of type of pointer then it is simple */
9010     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9011         p_type = DCL_TYPE(type);
9012     }
9013     else {
9014         /* we have to go by the storage class */
9015         p_type = PTR_TYPE(SPEC_OCLS(etype));
9016
9017 /*      if (SPEC_OCLS(etype)->codesp ) { */
9018 /*          p_type = CPOINTER ;  */
9019 /*      } */
9020 /*      else */
9021 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9022 /*              p_type = FPOINTER ; */
9023 /*          else */
9024 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9025 /*                  p_type = PPOINTER ; */
9026 /*              else */
9027 /*                  if (SPEC_OCLS(etype) == idata ) */
9028 /*                      p_type = IPOINTER ; */
9029 /*                  else */
9030 /*                      p_type = POINTER ; */
9031     }
9032
9033     /* now that we have the pointer type we assign
9034     the pointer values */
9035     switch (p_type) {
9036
9037     case POINTER:
9038     case IPOINTER:
9039         genNearPointerSet (right,result,ic);
9040         break;
9041
9042     case PPOINTER:
9043         genPagedPointerSet (right,result,ic);
9044         break;
9045
9046     case FPOINTER:
9047         genFarPointerSet (right,result,ic);
9048         break;
9049
9050     case GPOINTER:
9051         genGenPointerSet (right,result,ic);
9052         break;
9053
9054     default:
9055       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9056               "genPointerSet: illegal pointer type");
9057     }
9058 }
9059
9060 /*-----------------------------------------------------------------*/
9061 /* genIfx - generate code for Ifx statement                        */
9062 /*-----------------------------------------------------------------*/
9063 static void genIfx (iCode *ic, iCode *popIc)
9064 {
9065   operand *cond = IC_COND(ic);
9066   int isbit =0;
9067
9068   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9069
9070   aopOp(cond,ic,FALSE);
9071
9072   /* get the value into acc */
9073   if (AOP_TYPE(cond) != AOP_CRY)
9074     pic14_toBoolean(cond);
9075   else
9076     isbit = 1;
9077   /* the result is now in the accumulator */
9078   freeAsmop(cond,NULL,ic,TRUE);
9079
9080   /* if there was something to be popped then do it */
9081   if (popIc)
9082     genIpop(popIc);
9083
9084   /* if the condition is  a bit variable */
9085   if (isbit && IS_ITEMP(cond) && 
9086       SPIL_LOC(cond)) {
9087     genIfxJump(ic,SPIL_LOC(cond)->rname);
9088     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9089   }
9090   else {
9091     if (isbit && !IS_ITEMP(cond))
9092       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9093     else
9094       genIfxJump(ic,"a");
9095   }
9096   ic->generated = 1;
9097
9098 }
9099
9100 /*-----------------------------------------------------------------*/
9101 /* genAddrOf - generates code for address of                       */
9102 /*-----------------------------------------------------------------*/
9103 static void genAddrOf (iCode *ic)
9104 {
9105   operand *right, *result, *left;
9106   int size, offset ;
9107
9108   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9109
9110
9111   //aopOp(IC_RESULT(ic),ic,FALSE);
9112
9113   aopOp((left=IC_LEFT(ic)),ic,FALSE);
9114   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9115   aopOp((result=IC_RESULT(ic)),ic,TRUE);
9116
9117   DEBUGpic14_AopType(__LINE__,left,right,result);
9118
9119   size = AOP_SIZE(IC_RESULT(ic));
9120   offset = 0;
9121
9122   while (size--) {
9123         /* fixing bug #863624, reported from (errolv) */
9124         emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9125         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9126         
9127 #if 0
9128     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9129     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9130 #endif
9131     offset++;
9132   }
9133
9134   freeAsmop(left,NULL,ic,FALSE);
9135   freeAsmop(result,NULL,ic,TRUE);
9136
9137 }
9138
9139 #if 0
9140 /*-----------------------------------------------------------------*/
9141 /* genFarFarAssign - assignment when both are in far space         */
9142 /*-----------------------------------------------------------------*/
9143 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9144 {
9145     int size = AOP_SIZE(right);
9146     int offset = 0;
9147     char *l ;
9148     /* first push the right side on to the stack */
9149     while (size--) {
9150         l = aopGet(AOP(right),offset++,FALSE,FALSE);
9151         MOVA(l);
9152         pic14_emitcode ("push","acc");
9153     }
9154     
9155     freeAsmop(right,NULL,ic,FALSE);
9156     /* now assign DPTR to result */
9157     aopOp(result,ic,FALSE);
9158     size = AOP_SIZE(result);
9159     while (size--) {
9160         pic14_emitcode ("pop","acc");
9161         aopPut(AOP(result),"a",--offset);
9162     }
9163     freeAsmop(result,NULL,ic,FALSE);
9164         
9165 }
9166 #endif
9167
9168 /*-----------------------------------------------------------------*/
9169 /* genAssign - generate code for assignment                        */
9170 /*-----------------------------------------------------------------*/
9171 static void genAssign (iCode *ic)
9172 {
9173   operand *result, *right;
9174   int size, offset,know_W;
9175   unsigned long lit = 0L;
9176
9177   result = IC_RESULT(ic);
9178   right  = IC_RIGHT(ic) ;
9179
9180   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9181
9182   /* if they are the same */
9183   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9184     return ;
9185
9186   aopOp(right,ic,FALSE);
9187   aopOp(result,ic,TRUE);
9188
9189   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9190
9191   /* if they are the same registers */
9192   if (pic14_sameRegs(AOP(right),AOP(result)))
9193     goto release;
9194
9195   /* if the result is a bit */
9196   if (AOP_TYPE(result) == AOP_CRY) {
9197
9198     /* if the right size is a literal then
9199        we know what the value is */
9200     if (AOP_TYPE(right) == AOP_LIT) {
9201           
9202       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9203                   popGet(AOP(result),0));
9204
9205       if (((int) operandLitValue(right))) 
9206         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9207                        AOP(result)->aopu.aop_dir,
9208                        AOP(result)->aopu.aop_dir);
9209       else
9210         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9211                        AOP(result)->aopu.aop_dir,
9212                        AOP(result)->aopu.aop_dir);
9213       goto release;
9214     }
9215
9216     /* the right is also a bit variable */
9217     if (AOP_TYPE(right) == AOP_CRY) {
9218       emitpcode(POC_BCF,    popGet(AOP(result),0));
9219       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9220       emitpcode(POC_BSF,    popGet(AOP(result),0));
9221
9222       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9223                      AOP(result)->aopu.aop_dir,
9224                      AOP(result)->aopu.aop_dir);
9225       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9226                      AOP(right)->aopu.aop_dir,
9227                      AOP(right)->aopu.aop_dir);
9228       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9229                      AOP(result)->aopu.aop_dir,
9230                      AOP(result)->aopu.aop_dir);
9231       goto release ;
9232     }
9233
9234     /* we need to or */
9235     emitpcode(POC_BCF,    popGet(AOP(result),0));
9236     pic14_toBoolean(right);
9237     emitSKPZ;
9238     emitpcode(POC_BSF,    popGet(AOP(result),0));
9239     //aopPut(AOP(result),"a",0);
9240     goto release ;
9241   }
9242
9243   /* bit variables done */
9244   /* general case */
9245   size = AOP_SIZE(result);
9246   offset = 0 ;
9247   if(AOP_TYPE(right) == AOP_LIT)
9248     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9249
9250   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9251   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9252     if(aopIdx(AOP(result),0) == 4) {
9253   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9254       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9255       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9256       goto release;
9257     } else
9258       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9259   }
9260
9261   know_W=-1;
9262   while (size--) {
9263   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9264     if(AOP_TYPE(right) == AOP_LIT) {
9265       if(lit&0xff) {
9266         if(know_W != (int)(lit&0xff))
9267           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9268         know_W = lit&0xff;
9269         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9270       } else
9271         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9272
9273       lit >>= 8;
9274
9275     } else if (AOP_TYPE(right) == AOP_CRY) {
9276       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9277       if(offset == 0) {
9278         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9279         emitpcode(POC_INCF, popGet(AOP(result),0));
9280       }
9281     } else {
9282       mov2w (AOP(right), offset);
9283       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9284     }
9285             
9286     offset++;
9287   }
9288
9289     
9290  release:
9291   freeAsmop (right,NULL,ic,FALSE);
9292   freeAsmop (result,NULL,ic,TRUE);
9293 }   
9294
9295 /*-----------------------------------------------------------------*/
9296 /* genJumpTab - genrates code for jump table                       */
9297 /*-----------------------------------------------------------------*/
9298 static void genJumpTab (iCode *ic)
9299 {
9300     symbol *jtab;
9301     char *l;
9302
9303     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9304
9305     aopOp(IC_JTCOND(ic),ic,FALSE);
9306     /* get the condition into accumulator */
9307     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9308     MOVA(l);
9309     /* multiply by three */
9310     pic14_emitcode("add","a,acc");
9311     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9312
9313     jtab = newiTempLabel(NULL);
9314     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9315     pic14_emitcode("jmp","@a+dptr");
9316     pic14_emitcode("","%05d_DS_:",jtab->key+100);
9317
9318     emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9319     emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9320     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9321     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9322     emitSKPNC;
9323     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9324     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9325     emitpLabel(jtab->key);
9326
9327     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9328
9329     /* now generate the jump labels */
9330     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9331          jtab = setNextItem(IC_JTLABELS(ic))) {
9332         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9333         emitpcode(POC_GOTO,popGetLabel(jtab->key));
9334         
9335     }
9336
9337 }
9338
9339 /*-----------------------------------------------------------------*/
9340 /* genMixedOperation - gen code for operators between mixed types  */
9341 /*-----------------------------------------------------------------*/
9342 /*
9343   TSD - Written for the PIC port - but this unfortunately is buggy.
9344   This routine is good in that it is able to efficiently promote 
9345   types to different (larger) sizes. Unfortunately, the temporary
9346   variables that are optimized out by this routine are sometimes
9347   used in other places. So until I know how to really parse the 
9348   iCode tree, I'm going to not be using this routine :(.
9349 */
9350 static int genMixedOperation (iCode *ic)
9351 {
9352 #if 0
9353   operand *result = IC_RESULT(ic);
9354   sym_link *ctype = operandType(IC_LEFT(ic));
9355   operand *right = IC_RIGHT(ic);
9356   int ret = 0;
9357   int big,small;
9358   int offset;
9359
9360   iCode *nextic;
9361   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9362
9363   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9364
9365   nextic = ic->next;
9366   if(!nextic)
9367     return 0;
9368
9369   nextright = IC_RIGHT(nextic);
9370   nextleft  = IC_LEFT(nextic);
9371   nextresult = IC_RESULT(nextic);
9372
9373   aopOp(right,ic,FALSE);
9374   aopOp(result,ic,FALSE);
9375   aopOp(nextright,  nextic, FALSE);
9376   aopOp(nextleft,   nextic, FALSE);
9377   aopOp(nextresult, nextic, FALSE);
9378
9379   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9380
9381     operand *t = right;
9382     right = nextright;
9383     nextright = t; 
9384
9385     pic14_emitcode(";remove right +","");
9386
9387   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9388 /*
9389     operand *t = right;
9390     right = nextleft;
9391     nextleft = t; 
9392 */
9393     pic14_emitcode(";remove left +","");
9394   } else
9395     return 0;
9396
9397   big = AOP_SIZE(nextleft);
9398   small = AOP_SIZE(nextright);
9399
9400   switch(nextic->op) {
9401
9402   case '+':
9403     pic14_emitcode(";optimize a +","");
9404     /* if unsigned or not an integral type */
9405     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9406       pic14_emitcode(";add a bit to something","");
9407     } else {
9408
9409       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9410
9411       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9412         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9413         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9414       } else
9415         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9416
9417       offset = 0;
9418       while(--big) {
9419
9420         offset++;
9421
9422         if(--small) {
9423           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9424             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9425             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9426           }
9427
9428           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9429           emitSKPNC;
9430           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9431                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9432                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9433           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9434           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9435
9436         } else {
9437           pic14_emitcode("rlf","known_zero,w");
9438
9439           /*
9440             if right is signed
9441               btfsc  right,7
9442                addlw ff
9443           */
9444           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9445             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9446             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9447           } else {
9448             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9449           }
9450         }
9451       }
9452       ret = 1;
9453     }
9454   }
9455   ret = 1;
9456
9457 release:
9458   freeAsmop(right,NULL,ic,TRUE);
9459   freeAsmop(result,NULL,ic,TRUE);
9460   freeAsmop(nextright,NULL,ic,TRUE);
9461   freeAsmop(nextleft,NULL,ic,TRUE);
9462   if(ret)
9463     nextic->generated = 1;
9464
9465   return ret;
9466 #else
9467   return 0;
9468 #endif
9469 }
9470 /*-----------------------------------------------------------------*/
9471 /* genCast - gen code for casting                                  */
9472 /*-----------------------------------------------------------------*/
9473 static void genCast (iCode *ic)
9474 {
9475     operand *result = IC_RESULT(ic);
9476     sym_link *ctype = operandType(IC_LEFT(ic));
9477     sym_link *rtype = operandType(IC_RIGHT(ic));
9478     operand *right = IC_RIGHT(ic);
9479     int size, offset ;
9480
9481     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9482     /* if they are equivalent then do nothing */
9483     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9484         return ;
9485
9486     aopOp(right,ic,FALSE) ;
9487     aopOp(result,ic,FALSE);
9488
9489     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9490
9491     /* if the result is a bit */
9492     if (AOP_TYPE(result) == AOP_CRY) {
9493         /* if the right size is a literal then
9494         we know what the value is */
9495       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9496         if (AOP_TYPE(right) == AOP_LIT) {
9497
9498           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9499                       popGet(AOP(result),0));
9500
9501             if (((int) operandLitValue(right))) 
9502               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9503                        AOP(result)->aopu.aop_dir,
9504                        AOP(result)->aopu.aop_dir);
9505             else
9506               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9507                        AOP(result)->aopu.aop_dir,
9508                        AOP(result)->aopu.aop_dir);
9509
9510             goto release;
9511         }
9512
9513         /* the right is also a bit variable */
9514         if (AOP_TYPE(right) == AOP_CRY) {
9515
9516           emitCLRC;
9517           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9518
9519           pic14_emitcode("clrc","");
9520           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9521                    AOP(right)->aopu.aop_dir,
9522                    AOP(right)->aopu.aop_dir);
9523             aopPut(AOP(result),"c",0);
9524             goto release ;
9525         }
9526
9527         /* we need to or */
9528         if (AOP_TYPE(right) == AOP_REG) {
9529           emitpcode(POC_BCF,    popGet(AOP(result),0));
9530           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9531           emitpcode(POC_BSF,    popGet(AOP(result),0));
9532         }
9533         pic14_toBoolean(right);
9534         aopPut(AOP(result),"a",0);
9535         goto release ;
9536     }
9537
9538     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9539       int offset = 1;
9540       size = AOP_SIZE(result);
9541
9542       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9543
9544       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9545       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9546       emitpcode(POC_INCF,   popGet(AOP(result),0));
9547
9548       while (size--)
9549         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9550
9551       goto release;
9552     }
9553
9554     /* if they are the same size : or less */
9555     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9556
9557         /* if they are in the same place */
9558       if (pic14_sameRegs(AOP(right),AOP(result)))
9559         goto release;
9560
9561       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9562       if (IS_PTR_CONST(rtype))
9563         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9564       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9565         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9566
9567       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9568         emitpcode(POC_MOVLW, popGet(AOP(right),0));
9569         emitpcode(POC_MOVWF, popGet(AOP(result),0));
9570         emitpcode(POC_MOVLW, popGet(AOP(right),1));
9571         emitpcode(POC_MOVWF, popGet(AOP(result),1));
9572         if(AOP_SIZE(result) <2)
9573           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9574
9575       } else {
9576
9577         /* if they in different places then copy */
9578         size = AOP_SIZE(result);
9579         offset = 0 ;
9580         while (size--) {
9581           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9582           emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9583
9584           //aopPut(AOP(result),
9585           // aopGet(AOP(right),offset,FALSE,FALSE),
9586           // offset);
9587
9588           offset++;
9589         }
9590       }
9591       goto release;
9592     }
9593
9594
9595     /* if the result is of type pointer */
9596     if (IS_PTR(ctype)) {
9597
9598         int p_type;
9599         sym_link *type = operandType(right);
9600         sym_link *etype = getSpec(type);
9601       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9602
9603         /* pointer to generic pointer */
9604         if (IS_GENPTR(ctype)) {
9605             char *l = zero;
9606             
9607             if (IS_PTR(type)) 
9608                 p_type = DCL_TYPE(type);
9609             else {
9610                 /* we have to go by the storage class */
9611                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9612
9613 /*              if (SPEC_OCLS(etype)->codesp )  */
9614 /*                  p_type = CPOINTER ;  */
9615 /*              else */
9616 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9617 /*                      p_type = FPOINTER ; */
9618 /*                  else */
9619 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9620 /*                          p_type = PPOINTER; */
9621 /*                      else */
9622 /*                          if (SPEC_OCLS(etype) == idata ) */
9623 /*                              p_type = IPOINTER ; */
9624 /*                          else */
9625 /*                              p_type = POINTER ; */
9626             }
9627                 
9628             /* the first two bytes are known */
9629       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9630             size = GPTRSIZE - 1; 
9631             offset = 0 ;
9632             while (size--) {
9633               if(offset < AOP_SIZE(right)) {
9634       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9635                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9636                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9637                   emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9638                   emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9639                 } else { 
9640                   aopPut(AOP(result),
9641                          aopGet(AOP(right),offset,FALSE,FALSE),
9642                          offset);
9643                 }
9644               } else 
9645                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9646               offset++;
9647             }
9648             /* the last byte depending on type */
9649             switch (p_type) {
9650             case IPOINTER:
9651             case POINTER:
9652                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9653                 break;
9654             case FPOINTER:
9655               pic14_emitcode(";BUG!? ","%d",__LINE__);
9656                 l = one;
9657                 break;
9658             case CPOINTER:
9659               pic14_emitcode(";BUG!? ","%d",__LINE__);
9660                 l = "#0x02";
9661                 break;                          
9662             case PPOINTER:
9663               pic14_emitcode(";BUG!? ","%d",__LINE__);
9664                 l = "#0x03";
9665                 break;
9666                 
9667             default:
9668                 /* this should never happen */
9669                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9670                        "got unknown pointer type");
9671                 exit(1);
9672             }
9673             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9674             goto release ;
9675         }
9676         
9677         /* just copy the pointers */
9678         size = AOP_SIZE(result);
9679         offset = 0 ;
9680         while (size--) {
9681             aopPut(AOP(result),
9682                    aopGet(AOP(right),offset,FALSE,FALSE),
9683                    offset);
9684             offset++;
9685         }
9686         goto release ;
9687     }
9688     
9689
9690
9691     /* so we now know that the size of destination is greater
9692     than the size of the source.
9693     Now, if the next iCode is an operator then we might be
9694     able to optimize the operation without performing a cast.
9695     */
9696     if(genMixedOperation(ic))
9697       goto release;
9698
9699     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9700     
9701     /* we move to result for the size of source */
9702     size = AOP_SIZE(right);
9703     offset = 0 ;
9704     while (size--) {
9705       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9706       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9707       offset++;
9708     }
9709
9710     /* now depending on the sign of the destination */
9711     size = AOP_SIZE(result) - AOP_SIZE(right);
9712     /* if unsigned or not an integral type */
9713     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9714       while (size--)
9715         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9716     } else {
9717       /* we need to extend the sign :{ */
9718
9719       if(size == 1) {
9720         /* Save one instruction of casting char to int */
9721         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9722         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9723         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9724       } else {
9725         emitpcodeNULLop(POC_CLRW);
9726
9727         if(offset)
9728           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9729         else
9730           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9731         
9732         emitpcode(POC_MOVLW,   popGetLit(0xff));
9733
9734         while (size--)
9735           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9736       }
9737     }
9738
9739 release:
9740     freeAsmop(right,NULL,ic,TRUE);
9741     freeAsmop(result,NULL,ic,TRUE);
9742
9743 }
9744
9745 /*-----------------------------------------------------------------*/
9746 /* genDjnz - generate decrement & jump if not zero instrucion      */
9747 /*-----------------------------------------------------------------*/
9748 static int genDjnz (iCode *ic, iCode *ifx)
9749 {
9750     symbol *lbl, *lbl1;
9751     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9752
9753     if (!ifx)
9754         return 0;
9755     
9756     /* if the if condition has a false label
9757        then we cannot save */
9758     if (IC_FALSE(ifx))
9759         return 0;
9760
9761     /* if the minus is not of the form 
9762        a = a - 1 */
9763     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9764         !IS_OP_LITERAL(IC_RIGHT(ic)))
9765         return 0;
9766
9767     if (operandLitValue(IC_RIGHT(ic)) != 1)
9768         return 0;
9769
9770     /* if the size of this greater than one then no
9771        saving */
9772     if (getSize(operandType(IC_RESULT(ic))) > 1)
9773         return 0;
9774
9775     /* otherwise we can save BIG */
9776     lbl = newiTempLabel(NULL);
9777     lbl1= newiTempLabel(NULL);
9778
9779     aopOp(IC_RESULT(ic),ic,FALSE);
9780     
9781     if (IS_AOP_PREG(IC_RESULT(ic))) {
9782         pic14_emitcode("dec","%s",
9783                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9784         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9785         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9786     } else {    
9787
9788
9789       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9790       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9791
9792       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9793       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9794
9795     }
9796 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9797 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9798 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9799 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9800
9801     
9802     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9803     ifx->generated = 1;
9804     return 1;
9805 }
9806
9807 /*-----------------------------------------------------------------*/
9808 /* genReceive - generate code for a receive iCode                  */
9809 /*-----------------------------------------------------------------*/
9810 static void genReceive (iCode *ic)
9811 {
9812   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9813
9814   if (isOperandInFarSpace(IC_RESULT(ic)) &&
9815       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9816         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9817
9818     int size = getSize(operandType(IC_RESULT(ic)));
9819     int offset =  fReturnSizePic - size;
9820     while (size--) {
9821       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9822                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9823       offset++;
9824     }
9825     aopOp(IC_RESULT(ic),ic,FALSE);
9826     size = AOP_SIZE(IC_RESULT(ic));
9827     offset = 0;
9828     while (size--) {
9829       pic14_emitcode ("pop","acc");
9830       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9831     }
9832
9833   } else {
9834     _G.accInUse++;
9835     aopOp(IC_RESULT(ic),ic,FALSE);
9836     _G.accInUse--;
9837     assignResultValue(IC_RESULT(ic));
9838   }
9839
9840   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9841 }
9842
9843 /*-----------------------------------------------------------------*/
9844 /* genDummyRead - generate code for dummy read of volatiles        */
9845 /*-----------------------------------------------------------------*/
9846 static void
9847 genDummyRead (iCode * ic)
9848 {
9849   pic14_emitcode ("; genDummyRead","");
9850   pic14_emitcode ("; not implemented","");
9851
9852   ic = ic;
9853 }
9854
9855 /*-----------------------------------------------------------------*/
9856 /* genpic14Code - generate code for pic14 based controllers        */
9857 /*-----------------------------------------------------------------*/
9858 /*
9859  * At this point, ralloc.c has gone through the iCode and attempted
9860  * to optimize in a way suitable for a PIC. Now we've got to generate
9861  * PIC instructions that correspond to the iCode.
9862  *
9863  * Once the instructions are generated, we'll pass through both the
9864  * peep hole optimizer and the pCode optimizer.
9865  *-----------------------------------------------------------------*/
9866
9867 void genpic14Code (iCode *lic)
9868 {
9869     iCode *ic;
9870     int cln = 0;
9871
9872     lineHead = lineCurr = NULL;
9873
9874     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9875     addpBlock(pb);
9876
9877     /* if debug information required */
9878     if (options.debug && currFunc) { 
9879       if (currFunc) {
9880         debugFile->writeFunction(currFunc);
9881         _G.debugLine = 1;
9882         if (IS_STATIC(currFunc->etype)) {
9883           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9884           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9885         } else {
9886           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9887           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9888         }
9889         _G.debugLine = 0;
9890       }
9891     }
9892
9893
9894     for (ic = lic ; ic ; ic = ic->next ) {
9895
9896       DEBUGpic14_emitcode(";ic","");
9897         if ( cln != ic->lineno ) {
9898             if ( options.debug ) {
9899                 _G.debugLine = 1;
9900                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9901                          FileBaseName(ic->filename),ic->lineno,
9902                          ic->level,ic->block);
9903                 _G.debugLine = 0;
9904             }
9905             /*
9906               pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9907               pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9908               printCLine(ic->filename, ic->lineno));
9909             */
9910             if (!options.noCcodeInAsm) {
9911               addpCode2pBlock(pb,
9912                               newpCodeCSource(ic->lineno, 
9913                                               ic->filename, 
9914                                               printCLine(ic->filename, ic->lineno)));
9915             }
9916
9917             cln = ic->lineno ;
9918         }
9919
9920         // if you want printILine too, look at ../mcs51/gen.c, i don't understand this :)
9921
9922         /* if the result is marked as
9923            spilt and rematerializable or code for
9924            this has already been generated then
9925            do nothing */
9926         if (resultRemat(ic) || ic->generated ) 
9927             continue ;
9928         
9929         /* depending on the operation */
9930         switch (ic->op) {
9931         case '!' :
9932             genNot(ic);
9933             break;
9934             
9935         case '~' :
9936             genCpl(ic);
9937             break;
9938             
9939         case UNARYMINUS:
9940             genUminus (ic);
9941             break;
9942             
9943         case IPUSH:
9944             genIpush (ic);
9945             break;
9946             
9947         case IPOP:
9948             /* IPOP happens only when trying to restore a 
9949                spilt live range, if there is an ifx statement
9950                following this pop then the if statement might
9951                be using some of the registers being popped which
9952                would destory the contents of the register so
9953                we need to check for this condition and handle it */
9954             if (ic->next            && 
9955                 ic->next->op == IFX &&
9956                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9957                 genIfx (ic->next,ic);
9958             else
9959                 genIpop (ic);
9960             break; 
9961             
9962         case CALL:
9963             genCall (ic);
9964             break;
9965             
9966         case PCALL:
9967             genPcall (ic);
9968             break;
9969             
9970         case FUNCTION:
9971             genFunction (ic);
9972             break;
9973             
9974         case ENDFUNCTION:
9975             genEndFunction (ic);
9976             break;
9977             
9978         case RETURN:
9979             genRet (ic);
9980             break;
9981             
9982         case LABEL:
9983             genLabel (ic);
9984             break;
9985             
9986         case GOTO:
9987             genGoto (ic);
9988             break;
9989             
9990         case '+' :
9991             genPlus (ic) ;
9992             break;
9993             
9994         case '-' :
9995             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9996                 genMinus (ic);
9997             break;
9998             
9999         case '*' :
10000             genMult (ic);
10001             break;
10002             
10003         case '/' :
10004             genDiv (ic) ;
10005             break;
10006             
10007         case '%' :
10008             genMod (ic);
10009             break;
10010             
10011         case '>' :
10012             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10013             break;
10014             
10015         case '<' :
10016             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10017             break;
10018             
10019         case LE_OP:
10020         case GE_OP:
10021         case NE_OP:
10022             
10023             /* note these two are xlated by algebraic equivalence
10024                during parsing SDCC.y */
10025             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10026                    "got '>=' or '<=' shouldn't have come here");
10027             break;      
10028             
10029         case EQ_OP:
10030             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10031             break;          
10032             
10033         case AND_OP:
10034             genAndOp (ic);
10035             break;
10036             
10037         case OR_OP:
10038             genOrOp (ic);
10039             break;
10040             
10041         case '^' :
10042             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10043             break;
10044             
10045         case '|' :
10046                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10047             break;
10048             
10049         case BITWISEAND:
10050             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10051             break;
10052             
10053         case INLINEASM:
10054             genInline (ic);
10055             break;
10056             
10057         case RRC:
10058             genRRC (ic);
10059             break;
10060             
10061         case RLC:
10062             genRLC (ic);
10063             break;
10064             
10065         case GETHBIT:
10066             genGetHbit (ic);
10067             break;
10068             
10069         case LEFT_OP:
10070             genLeftShift (ic);
10071             break;
10072             
10073         case RIGHT_OP:
10074             genRightShift (ic);
10075             break;
10076             
10077         case GET_VALUE_AT_ADDRESS:
10078             genPointerGet(ic);
10079             break;
10080             
10081         case '=' :
10082             if (POINTER_SET(ic))
10083                 genPointerSet(ic);
10084             else
10085                 genAssign(ic);
10086             break;
10087             
10088         case IFX:
10089             genIfx (ic,NULL);
10090             break;
10091             
10092         case ADDRESS_OF:
10093             genAddrOf (ic);
10094             break;
10095             
10096         case JUMPTABLE:
10097             genJumpTab (ic);
10098             break;
10099             
10100         case CAST:
10101             genCast (ic);
10102             break;
10103             
10104         case RECEIVE:
10105             genReceive(ic);
10106             break;
10107             
10108         case SEND:
10109             addSet(&_G.sendSet,ic);
10110             break;
10111
10112         case DUMMY_READ_VOLATILE:
10113           genDummyRead (ic);
10114           break;
10115
10116         default :
10117             ic = ic;
10118         }
10119     }
10120
10121
10122     /* now we are ready to call the
10123        peep hole optimizer */
10124     if (!options.nopeep) {
10125       peepHole (&lineHead);
10126     }
10127     /* now do the actual printing */
10128     printLine (lineHead,codeOutFile);
10129
10130 #ifdef PCODE_DEBUG
10131     DFPRINTF((stderr,"printing pBlock\n\n"));
10132     printpBlock(stdout,pb);
10133 #endif
10134
10135     return;
10136 }