Pointers - Applied function ptr patch from Steve Tell. Fixed bugs with
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
29                 Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #include "common.h"
40 #include "SDCCpeeph.h"
41 #include "ralloc.h"
42 #include "pcode.h"
43 #include "gen.h"
44
45
46 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
47 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
48 void genMult8X8_8 (operand *, operand *,operand *);
49 pCode *AssembleLine(char *line);
50 extern void printpBlock(FILE *of, pBlock *pb);
51
52 static int labelOffset=0;
53 extern int debug_verbose;
54 static int optimized_for_speed = 0;
55
56 /* max_key keeps track of the largest label number used in 
57    a function. This is then used to adjust the label offset
58    for the next function.
59 */
60 static int max_key=0;
61 static int GpsuedoStkPtr=0;
62
63 pCodeOp *popGetImmd(char *name, unsigned int offset, int index);
64 unsigned int pic14aopLiteral (value *val, int offset);
65 const char *AopType(short type);
66 static iCode *ifxForOp ( operand *op, iCode *ic );
67
68 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
69
70 /* this is the down and dirty file with all kinds of 
71    kludgy & hacky stuff. This is what it is all about
72    CODE GENERATION for a specific MCU . some of the
73    routines may be reusable, will have to see */
74
75 static char *zero = "#0x00";
76 static char *one  = "#0x01";
77 static char *spname = "sp";
78
79 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
80 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
81 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
82 static char **fReturn = fReturnpic14;
83
84 static char *accUse[] = {"a","b"};
85
86 //static short rbank = -1;
87
88 static struct {
89     short r0Pushed;
90     short r1Pushed;
91     short accInUse;
92     short inLine;
93     short debugLine;
94     short nRegsSaved;
95     set *sendSet;
96 } _G;
97
98 /* Resolved ifx structure. This structure stores information
99    about an iCode ifx that makes it easier to generate code.
100 */
101 typedef struct resolvedIfx {
102   symbol *lbl;     /* pointer to a label */
103   int condition;   /* true or false ifx */
104   int generated;   /* set true when the code associated with the ifx
105                     * is generated */
106 } resolvedIfx;
107
108 extern int pic14_ptrRegReq ;
109 extern int pic14_nRegs;
110 extern FILE *codeOutFile;
111 static void saverbank (int, iCode *,bool);
112
113 static lineNode *lineHead = NULL;
114 static lineNode *lineCurr = NULL;
115
116 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
117 0xE0, 0xC0, 0x80, 0x00};
118 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
119 0x07, 0x03, 0x01, 0x00};
120
121 static  pBlock *pb;
122
123 /*-----------------------------------------------------------------*/
124 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
125 /*                 exponent of 2 is returned, otherwise -1 is      */
126 /*                 returned.                                       */
127 /* note that this is similar to the function `powof2' in SDCCsymt  */
128 /* if(n == 2^y)                                                    */
129 /*   return y;                                                     */
130 /* return -1;                                                      */
131 /*-----------------------------------------------------------------*/
132 static int my_powof2 (unsigned long num)
133 {
134   if(num) {
135     if( (num & (num-1)) == 0) {
136       int nshifts = -1;
137       while(num) {
138         num>>=1;
139         nshifts++;
140       }
141       return nshifts;
142     }
143   }
144
145   return -1;
146 }
147
148 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
149 {
150
151   DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
152                        line_no,
153                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
154                        ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
155                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
156                        ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
157                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
158                        ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
159                        ((result) ? AOP_SIZE(result) : 0));
160
161 }
162
163 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
164 {
165
166   DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
167                        line_no,
168                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
169                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
170                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
171                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
172                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
173                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
174
175 }
176
177 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
178 {
179     va_list ap;
180     char lb[INITIAL_INLINEASM];  
181     char *lbp = lb;
182
183     if(!debug_verbose)
184       return;
185
186     va_start(ap,fmt);   
187
188     if (inst && *inst) {
189         if (fmt && *fmt)
190             sprintf(lb,"%s\t",inst);
191         else
192             sprintf(lb,"%s",inst);
193         vsprintf(lb+(strlen(lb)),fmt,ap);
194     }  else
195         vsprintf(lb,fmt,ap);
196
197     while (isspace(*lbp)) lbp++;
198
199     if (lbp && *lbp) 
200         lineCurr = (lineCurr ?
201                     connectLine(lineCurr,newLineNode(lb)) :
202                     (lineHead = newLineNode(lb)));
203     lineCurr->isInline = _G.inLine;
204     lineCurr->isDebug  = _G.debugLine;
205
206     addpCode2pBlock(pb,newpCodeCharP(lb));
207
208     va_end(ap);
209 }
210
211
212 void emitpLabel(int key)
213 {
214   addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
215 }
216
217 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
218 {
219
220   if(pcop)
221     addpCode2pBlock(pb,newpCode(poc,pcop));
222   else
223     DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
224 }
225
226 void emitpcodeNULLop(PIC_OPCODE poc)
227 {
228
229   addpCode2pBlock(pb,newpCode(poc,NULL));
230
231 }
232
233 /*-----------------------------------------------------------------*/
234 /* pic14_emitcode - writes the code into a file : for now it is simple    */
235 /*-----------------------------------------------------------------*/
236 void pic14_emitcode (char *inst,char *fmt, ...)
237 {
238     va_list ap;
239     char lb[INITIAL_INLINEASM];  
240     char *lbp = lb;
241
242     va_start(ap,fmt);   
243
244     if (inst && *inst) {
245         if (fmt && *fmt)
246             sprintf(lb,"%s\t",inst);
247         else
248             sprintf(lb,"%s",inst);
249         vsprintf(lb+(strlen(lb)),fmt,ap);
250     }  else
251         vsprintf(lb,fmt,ap);
252
253     while (isspace(*lbp)) lbp++;
254
255     if (lbp && *lbp) 
256         lineCurr = (lineCurr ?
257                     connectLine(lineCurr,newLineNode(lb)) :
258                     (lineHead = newLineNode(lb)));
259     lineCurr->isInline = _G.inLine;
260     lineCurr->isDebug  = _G.debugLine;
261
262     if(debug_verbose)
263       addpCode2pBlock(pb,newpCodeCharP(lb));
264
265     va_end(ap);
266 }
267
268
269 /*-----------------------------------------------------------------*/
270 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
271 /*-----------------------------------------------------------------*/
272 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
273 {
274     bool r0iu = FALSE , r1iu = FALSE;
275     bool r0ou = FALSE , r1ou = FALSE;
276
277     /* the logic: if r0 & r1 used in the instruction
278     then we are in trouble otherwise */
279
280     /* first check if r0 & r1 are used by this
281     instruction, in which case we are in trouble */
282     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
283         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
284     {
285         goto endOfWorld;      
286     }
287
288     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
289     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
290
291     /* if no usage of r0 then return it */
292     if (!r0iu && !r0ou) {
293         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
294         (*aopp)->type = AOP_R0;
295         
296         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
297     }
298
299     /* if no usage of r1 then return it */
300     if (!r1iu && !r1ou) {
301         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
302         (*aopp)->type = AOP_R1;
303
304         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
305     }    
306
307     /* now we know they both have usage */
308     /* if r0 not used in this instruction */
309     if (!r0iu) {
310         /* push it if not already pushed */
311         if (!_G.r0Pushed) {
312           //pic14_emitcode ("push","%s",
313           //          pic14_regWithIdx(R0_IDX)->dname);
314             _G.r0Pushed++ ;
315         }
316         
317         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
318         (*aopp)->type = AOP_R0;
319
320         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
321     }
322
323     /* if r1 not used then */
324
325     if (!r1iu) {
326         /* push it if not already pushed */
327         if (!_G.r1Pushed) {
328           //pic14_emitcode ("push","%s",
329           //          pic14_regWithIdx(R1_IDX)->dname);
330             _G.r1Pushed++ ;
331         }
332         
333         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
334         (*aopp)->type = AOP_R1;
335         return pic14_regWithIdx(R1_IDX);
336     }
337
338 endOfWorld :
339     /* I said end of world but not quite end of world yet */
340     /* if this is a result then we can push it on the stack*/
341     if (result) {
342         (*aopp)->type = AOP_STK;    
343         return NULL;
344     }
345
346     /* other wise this is true end of the world */
347     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
348            "getFreePtr should never reach here");
349     exit(0);
350 }
351
352 /*-----------------------------------------------------------------*/
353 /* newAsmop - creates a new asmOp                                  */
354 /*-----------------------------------------------------------------*/
355 asmop *newAsmop (short type)
356 {
357     asmop *aop;
358
359     aop = Safe_calloc(1,sizeof(asmop));
360     aop->type = type;
361     return aop;
362 }
363
364 static void genSetDPTR(int n)
365 {
366     if (!n)
367     {
368         pic14_emitcode(";", "Select standard DPTR");
369         pic14_emitcode("mov", "dps, #0x00");
370     }
371     else
372     {
373         pic14_emitcode(";", "Select alternate DPTR");
374         pic14_emitcode("mov", "dps, #0x01");
375     }
376 }
377
378 /*-----------------------------------------------------------------*/
379 /* resolveIfx - converts an iCode ifx into a form more useful for  */
380 /*              generating code                                    */
381 /*-----------------------------------------------------------------*/
382 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
383 {
384   if(!resIfx) 
385     return;
386
387   //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
388
389   resIfx->condition = 1;    /* assume that the ifx is true */
390   resIfx->generated = 0;    /* indicate that the ifx has not been used */
391
392   if(!ifx) {
393     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
394 /*
395     DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
396                         __FUNCTION__,__LINE__,resIfx->lbl->key);
397 */
398   } else {
399     if(IC_TRUE(ifx)) {
400       resIfx->lbl = IC_TRUE(ifx);
401     } else {
402       resIfx->lbl = IC_FALSE(ifx);
403       resIfx->condition = 0;
404     }
405 /*
406     if(IC_TRUE(ifx)) 
407       DEBUGpic14_emitcode("; ***","ifx true is non-null");
408     if(IC_FALSE(ifx)) 
409       DEBUGpic14_emitcode("; ***","ifx false is non-null");
410 */
411   }
412
413   //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
414
415 }
416 /*-----------------------------------------------------------------*/
417 /* pointerCode - returns the code for a pointer type               */
418 /*-----------------------------------------------------------------*/
419 static int pointerCode (sym_link *etype)
420 {
421
422     return PTR_TYPE(SPEC_OCLS(etype));
423
424 }
425
426 /*-----------------------------------------------------------------*/
427 /* aopForSym - for a true symbol                                   */
428 /*-----------------------------------------------------------------*/
429 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
430 {
431     asmop *aop;
432     memmap *space= SPEC_OCLS(sym->etype);
433
434     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
435     /* if already has one */
436     if (sym->aop)
437         return sym->aop;
438
439     /* assign depending on the storage class */
440     /* if it is on the stack or indirectly addressable */
441     /* space we need to assign either r0 or r1 to it   */    
442     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
443         sym->aop = aop = newAsmop(0);
444         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
445         aop->size = getSize(sym->type);
446
447         /* now assign the address of the variable to 
448         the pointer register */
449         if (aop->type != AOP_STK) {
450
451             if (sym->onStack) {
452                     if ( _G.accInUse )
453                         pic14_emitcode("push","acc");
454
455                     pic14_emitcode("mov","a,_bp");
456                     pic14_emitcode("add","a,#0x%02x",
457                              ((sym->stack < 0) ?
458                               ((char)(sym->stack - _G.nRegsSaved )) :
459                               ((char)sym->stack)) & 0xff);
460                     pic14_emitcode("mov","%s,a",
461                              aop->aopu.aop_ptr->name);
462
463                     if ( _G.accInUse )
464                         pic14_emitcode("pop","acc");
465             } else
466                 pic14_emitcode("mov","%s,#%s",
467                          aop->aopu.aop_ptr->name,
468                          sym->rname);
469             aop->paged = space->paged;
470         } else
471             aop->aopu.aop_stk = sym->stack;
472         return aop;
473     }
474     
475     if (sym->onStack && options.stack10bit)
476     {
477         /* It's on the 10 bit stack, which is located in
478          * far data space.
479          */
480          
481       //DEBUGpic14_emitcode(";","%d",__LINE__);
482
483         if ( _G.accInUse )
484                 pic14_emitcode("push","acc");
485
486         pic14_emitcode("mov","a,_bp");
487         pic14_emitcode("add","a,#0x%02x",
488                  ((sym->stack < 0) ?
489                    ((char)(sym->stack - _G.nRegsSaved )) :
490                    ((char)sym->stack)) & 0xff);
491         
492         genSetDPTR(1);
493         pic14_emitcode ("mov","dpx1,#0x40");
494         pic14_emitcode ("mov","dph1,#0x00");
495         pic14_emitcode ("mov","dpl1, a");
496         genSetDPTR(0);
497         
498         if ( _G.accInUse )
499             pic14_emitcode("pop","acc");
500             
501         sym->aop = aop = newAsmop(AOP_DPTR2);
502         aop->size = getSize(sym->type); 
503         return aop;
504     }
505
506     //DEBUGpic14_emitcode(";","%d",__LINE__);
507     /* if in bit space */
508     if (IN_BITSPACE(space)) {
509         sym->aop = aop = newAsmop (AOP_CRY);
510         aop->aopu.aop_dir = sym->rname ;
511         aop->size = getSize(sym->type);
512         //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
513         return aop;
514     }
515     /* if it is in direct space */
516     if (IN_DIRSPACE(space)) {
517         sym->aop = aop = newAsmop (AOP_DIR);
518         aop->aopu.aop_dir = sym->rname ;
519         aop->size = getSize(sym->type);
520         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
521         return aop;
522     }
523
524     /* special case for a function */
525     if (IS_FUNC(sym->type)) {   
526         sym->aop = aop = newAsmop(AOP_IMMD);    
527         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
528         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
529         strcpy(aop->aopu.aop_immd,sym->rname);
530         aop->size = FPTRSIZE; 
531         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
532         return aop;
533     }
534
535
536     /* only remaining is far space */
537     /* in which case DPTR gets the address */
538     sym->aop = aop = newAsmop(AOP_PCODE);
539
540     aop->aopu.pcop = popGetImmd(sym->rname,0,0);
541     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
542     PCOI(aop->aopu.pcop)->index = 0;
543
544     DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
545                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
546
547     allocDirReg (IC_LEFT(ic));
548
549     aop->size = FPTRSIZE; 
550 /*
551     DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
552     sym->aop = aop = newAsmop(AOP_DPTR);
553     pic14_emitcode ("mov","dptr,#%s", sym->rname);
554     aop->size = getSize(sym->type);
555
556     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
557 */
558
559     /* if it is in code space */
560     if (IN_CODESPACE(space))
561         aop->code = 1;
562
563     return aop;     
564 }
565
566 /*-----------------------------------------------------------------*/
567 /* aopForRemat - rematerialzes an object                           */
568 /*-----------------------------------------------------------------*/
569 static asmop *aopForRemat (operand *op) // x symbol *sym)
570 {
571   symbol *sym = OP_SYMBOL(op);
572   iCode *ic = NULL;
573   asmop *aop = newAsmop(AOP_PCODE);
574   int val = 0;
575   int offset = 0;
576
577   ic = sym->rematiCode;
578
579   DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
580   if(IS_OP_POINTER(op)) {
581     DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
582   }
583   for (;;) {
584     if (ic->op == '+') {
585       val += (int) operandLitValue(IC_RIGHT(ic));
586     } else if (ic->op == '-') {
587       val -= (int) operandLitValue(IC_RIGHT(ic));
588     } else
589       break;
590         
591     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
592   }
593
594   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
595   aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
596   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
597   PCOI(aop->aopu.pcop)->index = val;
598
599   DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
600                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
601                       val, IS_PTR_CONST(operandType(op)));
602
603   //    DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
604
605   allocDirReg (IC_LEFT(ic));
606
607   return aop;        
608 }
609
610 int aopIdx (asmop *aop, int offset)
611 {
612   if(!aop)
613     return -1;
614
615   if(aop->type !=  AOP_REG)
616     return -2;
617         
618   return aop->aopu.aop_reg[offset]->rIdx;
619
620 }
621 /*-----------------------------------------------------------------*/
622 /* regsInCommon - two operands have some registers in common       */
623 /*-----------------------------------------------------------------*/
624 static bool regsInCommon (operand *op1, operand *op2)
625 {
626     symbol *sym1, *sym2;
627     int i;
628
629     /* if they have registers in common */
630     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
631         return FALSE ;
632
633     sym1 = OP_SYMBOL(op1);
634     sym2 = OP_SYMBOL(op2);
635
636     if (sym1->nRegs == 0 || sym2->nRegs == 0)
637         return FALSE ;
638
639     for (i = 0 ; i < sym1->nRegs ; i++) {
640         int j;
641         if (!sym1->regs[i])
642             continue ;
643
644         for (j = 0 ; j < sym2->nRegs ;j++ ) {
645             if (!sym2->regs[j])
646                 continue ;
647
648             if (sym2->regs[j] == sym1->regs[i])
649                 return TRUE ;
650         }
651     }
652
653     return FALSE ;
654 }
655
656 /*-----------------------------------------------------------------*/
657 /* operandsEqu - equivalent                                        */
658 /*-----------------------------------------------------------------*/
659 static bool operandsEqu ( operand *op1, operand *op2)
660 {
661     symbol *sym1, *sym2;
662
663     /* if they not symbols */
664     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
665         return FALSE;
666
667     sym1 = OP_SYMBOL(op1);
668     sym2 = OP_SYMBOL(op2);
669
670     /* if both are itemps & one is spilt
671        and the other is not then false */
672     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
673         sym1->isspilt != sym2->isspilt )
674         return FALSE ;
675
676     /* if they are the same */
677     if (sym1 == sym2)
678         return TRUE ;
679
680     if (strcmp(sym1->rname,sym2->rname) == 0)
681         return TRUE;
682
683
684     /* if left is a tmp & right is not */
685     if (IS_ITEMP(op1)  && 
686         !IS_ITEMP(op2) &&
687         sym1->isspilt  &&
688         (sym1->usl.spillLoc == sym2))
689         return TRUE;
690
691     if (IS_ITEMP(op2)  && 
692         !IS_ITEMP(op1) &&
693         sym2->isspilt  &&
694         sym1->level > 0 &&
695         (sym2->usl.spillLoc == sym1))
696         return TRUE ;
697
698     return FALSE ;
699 }
700
701 /*-----------------------------------------------------------------*/
702 /* pic14_sameRegs - two asmops have the same registers                   */
703 /*-----------------------------------------------------------------*/
704 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
705 {
706     int i;
707
708     if (aop1 == aop2)
709         return TRUE ;
710
711     if (aop1->type != AOP_REG ||
712         aop2->type != AOP_REG )
713         return FALSE ;
714
715     if (aop1->size != aop2->size )
716         return FALSE ;
717
718     for (i = 0 ; i < aop1->size ; i++ )
719         if (aop1->aopu.aop_reg[i] !=
720             aop2->aopu.aop_reg[i] )
721             return FALSE ;
722
723     return TRUE ;
724 }
725
726 /*-----------------------------------------------------------------*/
727 /* aopOp - allocates an asmop for an operand  :                    */
728 /*-----------------------------------------------------------------*/
729 void aopOp (operand *op, iCode *ic, bool result)
730 {
731     asmop *aop;
732     symbol *sym;
733     int i;
734
735     if (!op)
736         return ;
737
738     //    DEBUGpic14_emitcode(";","%d",__LINE__);
739     /* if this a literal */
740     if (IS_OP_LITERAL(op)) {
741         op->aop = aop = newAsmop(AOP_LIT);
742         aop->aopu.aop_lit = op->operand.valOperand;
743         aop->size = getSize(operandType(op));
744         return;
745     }
746
747     {
748       sym_link *type = operandType(op);
749       if(IS_PTR_CONST(type))
750         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
751     }
752
753     /* if already has a asmop then continue */
754     if (op->aop)
755         return ;
756
757     /* if the underlying symbol has a aop */
758     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
759       DEBUGpic14_emitcode(";","%d",__LINE__);
760         op->aop = OP_SYMBOL(op)->aop;
761         return;
762     }
763
764     /* if this is a true symbol */
765     if (IS_TRUE_SYMOP(op)) {    
766       //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
767       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
768       return ;
769     }
770
771     /* this is a temporary : this has
772     only four choices :
773     a) register
774     b) spillocation
775     c) rematerialize 
776     d) conditional   
777     e) can be a return use only */
778
779     sym = OP_SYMBOL(op);
780
781
782     /* if the type is a conditional */
783     if (sym->regType == REG_CND) {
784         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
785         aop->size = 0;
786         return;
787     }
788
789     /* if it is spilt then two situations
790     a) is rematerialize 
791     b) has a spill location */
792     if (sym->isspilt || sym->nRegs == 0) {
793
794       DEBUGpic14_emitcode(";","%d",__LINE__);
795         /* rematerialize it NOW */
796         if (sym->remat) {
797
798             sym->aop = op->aop = aop =
799                                       aopForRemat (op);
800             aop->size = getSize(sym->type);
801             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
802             return;
803         }
804
805         if (sym->accuse) {
806             int i;
807             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
808             aop->size = getSize(sym->type);
809             for ( i = 0 ; i < 2 ; i++ )
810                 aop->aopu.aop_str[i] = accUse[i];
811             DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
812             return;  
813         }
814
815         if (sym->ruonly ) {
816           if(sym->isptr) {  // && sym->uptr 
817             aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
818             aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
819
820             //PCOI(aop->aopu.pcop)->_const = 0;
821             //PCOI(aop->aopu.pcop)->index = 0;
822             /*
823               DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
824               __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
825             */
826             //allocDirReg (IC_LEFT(ic));
827
828             aop->size = getSize(sym->type);
829             DEBUGpic14_emitcode(";","%d",__LINE__);
830             return;
831
832           } else {
833
834             unsigned i;
835
836             aop = op->aop = sym->aop = newAsmop(AOP_STR);
837             aop->size = getSize(sym->type);
838             for ( i = 0 ; i < fReturnSizePic ; i++ )
839               aop->aopu.aop_str[i] = fReturn[i];
840
841             DEBUGpic14_emitcode(";","%d",__LINE__);
842             return;
843           }
844         }
845
846         /* else spill location  */
847         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
848             /* force a new aop if sizes differ */
849             sym->usl.spillLoc->aop = NULL;
850         }
851         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
852                             __FUNCTION__,__LINE__,
853                             sym->usl.spillLoc->rname,
854                             sym->rname, sym->usl.spillLoc->offset);
855
856         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
857         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
858         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
859                                           getSize(sym->type), 
860                                           sym->usl.spillLoc->offset);
861         aop->size = getSize(sym->type);
862
863         return;
864     }
865
866     {
867       sym_link *type = operandType(op);
868       if(IS_PTR_CONST(type)) 
869         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
870     }
871
872     /* must be in a register */
873     DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
874     sym->aop = op->aop = aop = newAsmop(AOP_REG);
875     aop->size = sym->nRegs;
876     for ( i = 0 ; i < sym->nRegs ;i++)
877         aop->aopu.aop_reg[i] = sym->regs[i];
878 }
879
880 /*-----------------------------------------------------------------*/
881 /* freeAsmop - free up the asmop given to an operand               */
882 /*----------------------------------------------------------------*/
883 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
884 {   
885     asmop *aop ;
886
887     if (!op)
888         aop = aaop;
889     else 
890         aop = op->aop;
891
892     if (!aop)
893         return ;
894
895     if (aop->freed)
896         goto dealloc; 
897
898     aop->freed = 1;
899
900     /* depending on the asmop type only three cases need work AOP_RO
901        , AOP_R1 && AOP_STK */
902 #if 0
903     switch (aop->type) {
904         case AOP_R0 :
905             if (_G.r0Pushed ) {
906                 if (pop) {
907                     pic14_emitcode ("pop","ar0");     
908                     _G.r0Pushed--;
909                 }
910             }
911             bitVectUnSetBit(ic->rUsed,R0_IDX);
912             break;
913
914         case AOP_R1 :
915             if (_G.r1Pushed ) {
916                 if (pop) {
917                     pic14_emitcode ("pop","ar1");
918                     _G.r1Pushed--;
919                 }
920             }
921             bitVectUnSetBit(ic->rUsed,R1_IDX);          
922             break;
923
924         case AOP_STK :
925         {
926             int sz = aop->size;    
927             int stk = aop->aopu.aop_stk + aop->size;
928             bitVectUnSetBit(ic->rUsed,R0_IDX);
929             bitVectUnSetBit(ic->rUsed,R1_IDX);          
930
931             getFreePtr(ic,&aop,FALSE);
932             
933             if (options.stack10bit)
934             {
935                 /* I'm not sure what to do here yet... */
936                 /* #STUB */
937                 fprintf(stderr, 
938                         "*** Warning: probably generating bad code for "
939                         "10 bit stack mode.\n");
940             }
941             
942             if (stk) {
943                 pic14_emitcode ("mov","a,_bp");
944                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
945                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
946             } else {
947                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
948             }
949
950             while (sz--) {
951                 pic14_emitcode("pop","acc");
952                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
953                 if (!sz) break;
954                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
955             }
956             op->aop = aop;
957             freeAsmop(op,NULL,ic,TRUE);
958             if (_G.r0Pushed) {
959                 pic14_emitcode("pop","ar0");
960                 _G.r0Pushed--;
961             }
962
963             if (_G.r1Pushed) {
964                 pic14_emitcode("pop","ar1");
965                 _G.r1Pushed--;
966             }       
967         }
968     }
969 #endif
970
971 dealloc:
972     /* all other cases just dealloc */
973     if (op ) {
974         op->aop = NULL;
975         if (IS_SYMOP(op)) {
976             OP_SYMBOL(op)->aop = NULL;    
977             /* if the symbol has a spill */
978             if (SPIL_LOC(op))
979                 SPIL_LOC(op)->aop = NULL;
980         }
981     }
982 }
983
984 /*-----------------------------------------------------------------*/
985 /* aopGet - for fetching value of the aop                          */
986 /*-----------------------------------------------------------------*/
987 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
988 {
989     char *s = buffer ;
990     char *rs;
991
992     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
993     /* offset is greater than
994     size then zero */
995     if (offset > (aop->size - 1) &&
996         aop->type != AOP_LIT)
997         return zero;
998
999     /* depending on type */
1000     switch (aop->type) {
1001         
1002     case AOP_R0:
1003     case AOP_R1:
1004         DEBUGpic14_emitcode(";","%d",__LINE__);
1005         /* if we need to increment it */       
1006         while (offset > aop->coff) {        
1007             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1008             aop->coff++;
1009         }
1010         
1011         while (offset < aop->coff) {
1012             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1013             aop->coff--;
1014         }
1015         
1016         aop->coff = offset ;
1017         if (aop->paged) {
1018             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1019             return (dname ? "acc" : "a");
1020         }       
1021         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1022         rs = Safe_calloc(1,strlen(s)+1);
1023         strcpy(rs,s);   
1024         return rs;
1025         
1026     case AOP_DPTR:
1027     case AOP_DPTR2:
1028         DEBUGpic14_emitcode(";","%d",__LINE__);
1029     if (aop->type == AOP_DPTR2)
1030     {
1031         genSetDPTR(1);
1032     }
1033     
1034         while (offset > aop->coff) {
1035             pic14_emitcode ("inc","dptr");
1036             aop->coff++;
1037         }
1038         
1039         while (offset < aop->coff) {        
1040             pic14_emitcode("lcall","__decdptr");
1041             aop->coff--;
1042         }
1043         
1044         aop->coff = offset;
1045         if (aop->code) {
1046             pic14_emitcode("clr","a");
1047             pic14_emitcode("movc","a,@a+dptr");
1048         }
1049     else {
1050             pic14_emitcode("movx","a,@dptr");
1051     }
1052             
1053     if (aop->type == AOP_DPTR2)
1054     {
1055         genSetDPTR(0);
1056     }
1057             
1058     return (dname ? "acc" : "a");
1059         
1060         
1061     case AOP_IMMD:
1062         if (bit16) 
1063             sprintf (s,"%s",aop->aopu.aop_immd);
1064         else
1065             if (offset) 
1066                 sprintf(s,"(%s >> %d)",
1067                         aop->aopu.aop_immd,
1068                         offset*8);
1069             else
1070                 sprintf(s,"%s",
1071                         aop->aopu.aop_immd);
1072         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1073         rs = Safe_calloc(1,strlen(s)+1);
1074         strcpy(rs,s);   
1075         return rs;
1076         
1077     case AOP_DIR:
1078       if (offset) {
1079         sprintf(s,"(%s + %d)",
1080                 aop->aopu.aop_dir,
1081                 offset);
1082         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1083       } else
1084             sprintf(s,"%s",aop->aopu.aop_dir);
1085         rs = Safe_calloc(1,strlen(s)+1);
1086         strcpy(rs,s);   
1087         return rs;
1088         
1089     case AOP_REG:
1090       //if (dname) 
1091       //    return aop->aopu.aop_reg[offset]->dname;
1092       //else
1093             return aop->aopu.aop_reg[offset]->name;
1094         
1095     case AOP_CRY:
1096       //pic14_emitcode(";","%d",__LINE__);
1097       return aop->aopu.aop_dir;
1098         
1099     case AOP_ACC:
1100         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1101         return "AOP_accumulator_bug";
1102
1103     case AOP_LIT:
1104         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1105         rs = Safe_calloc(1,strlen(s)+1);
1106         strcpy(rs,s);   
1107         return rs;
1108         
1109     case AOP_STR:
1110         aop->coff = offset ;
1111         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1112             dname)
1113             return "acc";
1114         DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1115         
1116         return aop->aopu.aop_str[offset];
1117         
1118     case AOP_PCODE:
1119       {
1120         pCodeOp *pcop = aop->aopu.pcop;
1121         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1122         if(pcop->name) {
1123           DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1124           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1125           sprintf(s,"%s", pcop->name);
1126         } else
1127           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1128
1129       }
1130       rs = Safe_calloc(1,strlen(s)+1);
1131       strcpy(rs,s);   
1132       return rs;
1133
1134     }
1135
1136     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1137            "aopget got unsupported aop->type");
1138     exit(0);
1139 }
1140
1141
1142 /*-----------------------------------------------------------------*/
1143 /* popGetTempReg - create a new temporary pCodeOp                  */
1144 /*-----------------------------------------------------------------*/
1145 pCodeOp *popGetTempReg(void)
1146 {
1147
1148   pCodeOp *pcop;
1149
1150   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1151   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1152     PCOR(pcop)->r->wasUsed=1;
1153     PCOR(pcop)->r->isFree=0;
1154   }
1155
1156   return pcop;
1157 }
1158
1159 /*-----------------------------------------------------------------*/
1160 /* popGetTempReg - create a new temporary pCodeOp                  */
1161 /*-----------------------------------------------------------------*/
1162 void popReleaseTempReg(pCodeOp *pcop)
1163 {
1164
1165   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1166     PCOR(pcop)->r->isFree = 1;
1167
1168 }
1169 /*-----------------------------------------------------------------*/
1170 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1171 /*-----------------------------------------------------------------*/
1172 pCodeOp *popGetLabel(unsigned int key)
1173 {
1174
1175   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1176
1177   if(key>max_key)
1178     max_key = key;
1179
1180   return newpCodeOpLabel(NULL,key+100+labelOffset);
1181 }
1182
1183 /*-----------------------------------------------------------------*/
1184 /* popCopyReg - copy a pcode operator                              */
1185 /*-----------------------------------------------------------------*/
1186 pCodeOp *popCopyReg(pCodeOpReg *pc)
1187 {
1188   pCodeOpReg *pcor;
1189
1190   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1191   pcor->pcop.type = pc->pcop.type;
1192   if(pc->pcop.name) {
1193     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1194       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1195   } else
1196     pcor->pcop.name = NULL;
1197
1198   pcor->r = pc->r;
1199   pcor->rIdx = pc->rIdx;
1200   pcor->r->wasUsed=1;
1201
1202   //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1203
1204   return PCOP(pcor);
1205 }
1206 /*-----------------------------------------------------------------*/
1207 /* popGet - asm operator to pcode operator conversion              */
1208 /*-----------------------------------------------------------------*/
1209 pCodeOp *popGetLit(unsigned int lit)
1210 {
1211
1212   return newpCodeOpLit(lit);
1213 }
1214
1215
1216 /*-----------------------------------------------------------------*/
1217 /* popGetImmd - asm operator to pcode immediate conversion         */
1218 /*-----------------------------------------------------------------*/
1219 pCodeOp *popGetImmd(char *name, unsigned int offset, int index)
1220 {
1221
1222   return newpCodeOpImmd(name, offset,index, 0);
1223 }
1224
1225
1226 /*-----------------------------------------------------------------*/
1227 /* popGet - asm operator to pcode operator conversion              */
1228 /*-----------------------------------------------------------------*/
1229 pCodeOp *popGetWithString(char *str)
1230 {
1231   pCodeOp *pcop;
1232
1233
1234   if(!str) {
1235     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1236     exit (1);
1237   }
1238
1239   pcop = newpCodeOp(str,PO_STR);
1240
1241   return pcop;
1242 }
1243
1244 /*-----------------------------------------------------------------*/
1245 /* popRegFromString -                                              */
1246 /*-----------------------------------------------------------------*/
1247 pCodeOp *popRegFromString(char *str, int size, int offset)
1248 {
1249
1250   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1251   pcop->type = PO_DIR;
1252
1253   DEBUGpic14_emitcode(";","%d",__LINE__);
1254
1255   if(!str)
1256     str = "BAD_STRING";
1257
1258   pcop->name = Safe_calloc(1,strlen(str)+1);
1259   strcpy(pcop->name,str);
1260
1261   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1262
1263   PCOR(pcop)->r = dirregWithName(pcop->name);
1264   if(PCOR(pcop)->r == NULL) {
1265     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1266     PCOR(pcop)->r = allocRegByName (pcop->name,size);
1267     DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1268   } else {
1269     DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1270   }
1271   PCOR(pcop)->instance = offset;
1272
1273   return pcop;
1274 }
1275
1276 pCodeOp *popRegFromIdx(int rIdx)
1277 {
1278   pCodeOp *pcop;
1279
1280   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1281                        __FUNCTION__,__LINE__,rIdx);
1282
1283   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1284
1285   PCOR(pcop)->rIdx = rIdx;
1286   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1287   PCOR(pcop)->r->isFree = 0;
1288   PCOR(pcop)->r->wasUsed = 1;
1289
1290   pcop->type = PCOR(pcop)->r->pc_type;
1291
1292
1293   return pcop;
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);
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));
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 /* genNotFloat - generates not for float operations              */
1704 /*-----------------------------------------------------------------*/
1705 static void genNotFloat (operand *op, operand *res)
1706 {
1707     int size, offset;
1708     char *l;
1709     symbol *tlbl ;
1710
1711     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1712     /* we will put 127 in the first byte of 
1713     the result */
1714     aopPut(AOP(res),"#127",0);
1715     size = AOP_SIZE(op) - 1;
1716     offset = 1;
1717
1718     l = aopGet(op->aop,offset++,FALSE,FALSE);
1719     MOVA(l);    
1720
1721     while(size--) {
1722         pic14_emitcode("orl","a,%s",
1723                  aopGet(op->aop,
1724                         offset++,FALSE,FALSE));
1725     }
1726     tlbl = newiTempLabel(NULL);
1727
1728     tlbl = newiTempLabel(NULL);
1729     aopPut(res->aop,one,1);
1730     pic14_emitcode("jz","%05d_DS_",(tlbl->key+100));
1731     aopPut(res->aop,zero,1);
1732     pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
1733
1734     size = res->aop->size - 2;
1735     offset = 2;    
1736     /* put zeros in the rest */
1737     while (size--) 
1738         aopPut(res->aop,zero,offset++);
1739 }
1740
1741 #if 0
1742 /*-----------------------------------------------------------------*/
1743 /* opIsGptr: returns non-zero if the passed operand is             */   
1744 /* a generic pointer type.                                         */
1745 /*-----------------------------------------------------------------*/ 
1746 static int opIsGptr(operand *op)
1747 {
1748     sym_link *type = operandType(op);
1749     
1750     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1751     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1752     {
1753         return 1;
1754     }
1755     return 0;        
1756 }
1757 #endif
1758
1759 /*-----------------------------------------------------------------*/
1760 /* pic14_getDataSize - get the operand data size                         */
1761 /*-----------------------------------------------------------------*/
1762 int pic14_getDataSize(operand *op)
1763 {
1764     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1765
1766
1767     return AOP_SIZE(op);
1768
1769     // tsd- in the pic port, the genptr size is 1, so this code here
1770     // fails. ( in the 8051 port, the size was 4).
1771 #if 0
1772     int size;
1773     size = AOP_SIZE(op);
1774     if (size == GPTRSIZE)
1775     {
1776         sym_link *type = operandType(op);
1777         if (IS_GENPTR(type))
1778         {
1779             /* generic pointer; arithmetic operations
1780              * should ignore the high byte (pointer type).
1781              */
1782             size--;
1783     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1784         }
1785     }
1786     return size;
1787 #endif
1788 }
1789
1790 /*-----------------------------------------------------------------*/
1791 /* pic14_outAcc - output Acc                                             */
1792 /*-----------------------------------------------------------------*/
1793 void pic14_outAcc(operand *result)
1794 {
1795   int size,offset;
1796   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1797   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1798
1799
1800   size = pic14_getDataSize(result);
1801   if(size){
1802     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1803     size--;
1804     offset = 1;
1805     /* unsigned or positive */
1806     while(size--)
1807       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1808   }
1809
1810 }
1811
1812 /*-----------------------------------------------------------------*/
1813 /* pic14_outBitC - output a bit C                                        */
1814 /*-----------------------------------------------------------------*/
1815 void pic14_outBitC(operand *result)
1816 {
1817
1818     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1819     /* if the result is bit */
1820     if (AOP_TYPE(result) == AOP_CRY) 
1821         aopPut(AOP(result),"c",0);
1822     else {
1823         pic14_emitcode("clr","a  ; %d", __LINE__);
1824         pic14_emitcode("rlc","a");
1825         pic14_outAcc(result);
1826     }
1827 }
1828
1829 /*-----------------------------------------------------------------*/
1830 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1831 /*-----------------------------------------------------------------*/
1832 void pic14_toBoolean(operand *oper)
1833 {
1834     int size = AOP_SIZE(oper) - 1;
1835     int offset = 1;
1836
1837     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1838
1839     if ( AOP_TYPE(oper) != AOP_ACC) {
1840       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1841     }
1842     while (size--) {
1843       emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1844     }
1845 }
1846
1847
1848 /*-----------------------------------------------------------------*/
1849 /* genNot - generate code for ! operation                          */
1850 /*-----------------------------------------------------------------*/
1851 static void genNot (iCode *ic)
1852 {
1853   symbol *tlbl;
1854   sym_link *optype = operandType(IC_LEFT(ic));
1855   int size;
1856
1857   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1858   /* assign asmOps to operand & result */
1859   aopOp (IC_LEFT(ic),ic,FALSE);
1860   aopOp (IC_RESULT(ic),ic,TRUE);
1861
1862   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1863   /* if in bit space then a special case */
1864   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1865     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1866       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1867       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1868     } else {
1869       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1870       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1871       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1872     }
1873     goto release;
1874   }
1875
1876   /* if type float then do float */
1877   if (IS_FLOAT(optype)) {
1878     genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1879     goto release;
1880   }
1881
1882   size = AOP_SIZE(IC_RESULT(ic));
1883   if(size == 1) {
1884     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1885     emitpcode(POC_ANDLW,popGetLit(1));
1886     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1887     goto release;
1888   }
1889   pic14_toBoolean(IC_LEFT(ic));
1890
1891   tlbl = newiTempLabel(NULL);
1892   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1893   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1894   pic14_outBitC(IC_RESULT(ic));
1895
1896  release:    
1897   /* release the aops */
1898   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1899   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1900 }
1901
1902
1903 /*-----------------------------------------------------------------*/
1904 /* genCpl - generate code for complement                           */
1905 /*-----------------------------------------------------------------*/
1906 static void genCpl (iCode *ic)
1907 {
1908   operand *left, *result;
1909   int size, offset=0;  
1910
1911
1912   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1913   aopOp((left = IC_LEFT(ic)),ic,FALSE);
1914   aopOp((result=IC_RESULT(ic)),ic,TRUE);
1915
1916   /* if both are in bit space then 
1917      a special case */
1918   if (AOP_TYPE(result) == AOP_CRY &&
1919       AOP_TYPE(left) == AOP_CRY ) { 
1920
1921     pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1922     pic14_emitcode("cpl","c"); 
1923     pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1924     goto release; 
1925   } 
1926
1927   size = AOP_SIZE(result);
1928   while (size--) {
1929
1930     if(AOP_TYPE(left) == AOP_ACC) 
1931       emitpcode(POC_XORLW, popGetLit(0xff));
1932     else
1933       emitpcode(POC_COMFW,popGet(AOP(left),offset));
1934
1935     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1936
1937   }
1938
1939
1940 release:
1941     /* release the aops */
1942     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1943     freeAsmop(result,NULL,ic,TRUE);
1944 }
1945
1946 /*-----------------------------------------------------------------*/
1947 /* genUminusFloat - unary minus for floating points                */
1948 /*-----------------------------------------------------------------*/
1949 static void genUminusFloat(operand *op,operand *result)
1950 {
1951     int size ,offset =0 ;
1952     char *l;
1953
1954     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1955     /* for this we just need to flip the 
1956     first it then copy the rest in place */
1957     size = AOP_SIZE(op) - 1;
1958     l = aopGet(AOP(op),3,FALSE,FALSE);
1959
1960     MOVA(l);    
1961
1962     pic14_emitcode("cpl","acc.7");
1963     aopPut(AOP(result),"a",3);    
1964
1965     while(size--) {
1966         aopPut(AOP(result),
1967                aopGet(AOP(op),offset,FALSE,FALSE),
1968                offset);
1969         offset++;
1970     }          
1971 }
1972
1973 /*-----------------------------------------------------------------*/
1974 /* genUminus - unary minus code generation                         */
1975 /*-----------------------------------------------------------------*/
1976 static void genUminus (iCode *ic)
1977 {
1978   int size, i;
1979   sym_link *optype, *rtype;
1980
1981
1982   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1983   /* assign asmops */
1984   aopOp(IC_LEFT(ic),ic,FALSE);
1985   aopOp(IC_RESULT(ic),ic,TRUE);
1986
1987   /* if both in bit space then special
1988      case */
1989   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1990       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1991
1992     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1993     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1994     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1995
1996     goto release; 
1997   } 
1998
1999   optype = operandType(IC_LEFT(ic));
2000   rtype = operandType(IC_RESULT(ic));
2001
2002   /* if float then do float stuff */
2003   if (IS_FLOAT(optype)) {
2004     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2005     goto release;
2006   }
2007
2008   /* otherwise subtract from zero by taking the 2's complement */
2009   size = AOP_SIZE(IC_LEFT(ic));
2010
2011   for(i=0; i<size; i++) {
2012     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2013       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2014     else {
2015       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2016       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2017     }
2018   }
2019
2020   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2021   for(i=1; i<size; i++) {
2022     emitSKPNZ;
2023     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2024   }
2025
2026  release:
2027   /* release the aops */
2028   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2029   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2030 }
2031
2032 /*-----------------------------------------------------------------*/
2033 /* saveRegisters - will look for a call and save the registers     */
2034 /*-----------------------------------------------------------------*/
2035 static void saveRegisters(iCode *lic) 
2036 {
2037     int i;
2038     iCode *ic;
2039     bitVect *rsave;
2040     sym_link *dtype;
2041
2042     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2043     /* look for call */
2044     for (ic = lic ; ic ; ic = ic->next) 
2045         if (ic->op == CALL || ic->op == PCALL)
2046             break;
2047
2048     if (!ic) {
2049         fprintf(stderr,"found parameter push with no function call\n");
2050         return ;
2051     }
2052
2053     /* if the registers have been saved already then
2054     do nothing */
2055     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2056         return ;
2057
2058     /* find the registers in use at this time 
2059     and push them away to safety */
2060     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2061                           ic->rUsed);
2062
2063     ic->regsSaved = 1;
2064     if (options.useXstack) {
2065         if (bitVectBitValue(rsave,R0_IDX))
2066             pic14_emitcode("mov","b,r0");
2067         pic14_emitcode("mov","r0,%s",spname);
2068         for (i = 0 ; i < pic14_nRegs ; i++) {
2069             if (bitVectBitValue(rsave,i)) {
2070                 if (i == R0_IDX)
2071                     pic14_emitcode("mov","a,b");
2072                 else
2073                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2074                 pic14_emitcode("movx","@r0,a");
2075                 pic14_emitcode("inc","r0");
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 = 0 ; i < pic14_nRegs ; i++) {
2083     //    if (bitVectBitValue(rsave,i))
2084     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2085     //}
2086
2087     dtype = operandType(IC_LEFT(ic));
2088     if (currFunc && dtype && 
2089         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2090         IFFUNC_ISISR(currFunc->type) &&
2091         !ic->bankSaved) 
2092
2093         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2094
2095 }
2096 /*-----------------------------------------------------------------*/
2097 /* unsaveRegisters - pop the pushed registers                      */
2098 /*-----------------------------------------------------------------*/
2099 static void unsaveRegisters (iCode *ic)
2100 {
2101     int i;
2102     bitVect *rsave;
2103
2104     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2105     /* find the registers in use at this time 
2106     and push them away to safety */
2107     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2108                           ic->rUsed);
2109     
2110     if (options.useXstack) {
2111         pic14_emitcode("mov","r0,%s",spname);   
2112         for (i =  pic14_nRegs ; i >= 0 ; i--) {
2113             if (bitVectBitValue(rsave,i)) {
2114                 pic14_emitcode("dec","r0");
2115                 pic14_emitcode("movx","a,@r0");
2116                 if (i == R0_IDX)
2117                     pic14_emitcode("mov","b,a");
2118                 else
2119                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2120             }       
2121
2122         }
2123         pic14_emitcode("mov","%s,r0",spname);
2124         if (bitVectBitValue(rsave,R0_IDX))
2125             pic14_emitcode("mov","r0,b");
2126     } //else
2127     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2128     //    if (bitVectBitValue(rsave,i))
2129     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2130     //}
2131
2132 }  
2133
2134
2135 /*-----------------------------------------------------------------*/
2136 /* pushSide -                                                      */
2137 /*-----------------------------------------------------------------*/
2138 static void pushSide(operand * oper, int size)
2139 {
2140 #if 0
2141         int offset = 0;
2142     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2143         while (size--) {
2144                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2145                 if (AOP_TYPE(oper) != AOP_REG &&
2146                     AOP_TYPE(oper) != AOP_DIR &&
2147                     strcmp(l,"a") ) {
2148                         pic14_emitcode("mov","a,%s",l);
2149                         pic14_emitcode("push","acc");
2150                 } else
2151                         pic14_emitcode("push","%s",l);
2152         }
2153 #endif
2154 }
2155
2156 /*-----------------------------------------------------------------*/
2157 /* assignResultValue -                                             */
2158 /*-----------------------------------------------------------------*/
2159 static void assignResultValue(operand * oper)
2160 {
2161   int size = AOP_SIZE(oper);
2162
2163   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2164
2165   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2166
2167   if(!GpsuedoStkPtr) {
2168     /* The last byte in the assignment is in W */
2169     size--;
2170     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2171     GpsuedoStkPtr++;
2172   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2173   }
2174
2175   while (size--) {
2176     emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
2177     GpsuedoStkPtr++;
2178     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2179   }
2180 }
2181
2182
2183 /*-----------------------------------------------------------------*/
2184 /* genIpush - genrate code for pushing this gets a little complex  */
2185 /*-----------------------------------------------------------------*/
2186 static void genIpush (iCode *ic)
2187 {
2188
2189   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2190 #if 0
2191     int size, offset = 0 ;
2192     char *l;
2193
2194
2195     /* if this is not a parm push : ie. it is spill push 
2196     and spill push is always done on the local stack */
2197     if (!ic->parmPush) {
2198
2199         /* and the item is spilt then do nothing */
2200         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2201             return ;
2202
2203         aopOp(IC_LEFT(ic),ic,FALSE);
2204         size = AOP_SIZE(IC_LEFT(ic));
2205         /* push it on the stack */
2206         while(size--) {
2207             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2208             if (*l == '#') {
2209                 MOVA(l);
2210                 l = "acc";
2211             }
2212             pic14_emitcode("push","%s",l);
2213         }
2214         return ;        
2215     }
2216
2217     /* this is a paramter push: in this case we call
2218     the routine to find the call and save those
2219     registers that need to be saved */   
2220     saveRegisters(ic);
2221
2222     /* then do the push */
2223     aopOp(IC_LEFT(ic),ic,FALSE);
2224
2225
2226         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2227     size = AOP_SIZE(IC_LEFT(ic));
2228
2229     while (size--) {
2230         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2231         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2232             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2233             strcmp(l,"a") ) {
2234             pic14_emitcode("mov","a,%s",l);
2235             pic14_emitcode("push","acc");
2236         } else
2237             pic14_emitcode("push","%s",l);
2238     }       
2239
2240     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2241 #endif
2242 }
2243
2244 /*-----------------------------------------------------------------*/
2245 /* genIpop - recover the registers: can happen only for spilling   */
2246 /*-----------------------------------------------------------------*/
2247 static void genIpop (iCode *ic)
2248 {
2249   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2250 #if 0
2251     int size,offset ;
2252
2253
2254     /* if the temp was not pushed then */
2255     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2256         return ;
2257
2258     aopOp(IC_LEFT(ic),ic,FALSE);
2259     size = AOP_SIZE(IC_LEFT(ic));
2260     offset = (size-1);
2261     while (size--) 
2262         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2263                                    FALSE,TRUE));
2264
2265     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2266 #endif
2267 }
2268
2269 /*-----------------------------------------------------------------*/
2270 /* unsaverbank - restores the resgister bank from stack            */
2271 /*-----------------------------------------------------------------*/
2272 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2273 {
2274   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2275 #if 0
2276     int i;
2277     asmop *aop ;
2278     regs *r = NULL;
2279
2280     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2281     if (popPsw) {
2282         if (options.useXstack) {
2283             aop = newAsmop(0);
2284             r = getFreePtr(ic,&aop,FALSE);
2285             
2286             
2287             pic14_emitcode("mov","%s,_spx",r->name);
2288             pic14_emitcode("movx","a,@%s",r->name);
2289             pic14_emitcode("mov","psw,a");
2290             pic14_emitcode("dec","%s",r->name);
2291             
2292         }else
2293             pic14_emitcode ("pop","psw");
2294     }
2295
2296     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2297         if (options.useXstack) {       
2298             pic14_emitcode("movx","a,@%s",r->name);
2299             //pic14_emitcode("mov","(%s+%d),a",
2300             //       regspic14[i].base,8*bank+regspic14[i].offset);
2301             pic14_emitcode("dec","%s",r->name);
2302
2303         } else 
2304           pic14_emitcode("pop",""); //"(%s+%d)",
2305         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2306     }
2307
2308     if (options.useXstack) {
2309
2310         pic14_emitcode("mov","_spx,%s",r->name);
2311         freeAsmop(NULL,aop,ic,TRUE);
2312
2313     }
2314 #endif 
2315 }
2316
2317 /*-----------------------------------------------------------------*/
2318 /* saverbank - saves an entire register bank on the stack          */
2319 /*-----------------------------------------------------------------*/
2320 static void saverbank (int bank, iCode *ic, bool pushPsw)
2321 {
2322   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2323 #if 0
2324     int i;
2325     asmop *aop ;
2326     regs *r = NULL;
2327
2328     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2329     if (options.useXstack) {
2330
2331         aop = newAsmop(0);
2332         r = getFreePtr(ic,&aop,FALSE);  
2333         pic14_emitcode("mov","%s,_spx",r->name);
2334
2335     }
2336
2337     for (i = 0 ; i < pic14_nRegs ;i++) {
2338         if (options.useXstack) {
2339             pic14_emitcode("inc","%s",r->name);
2340             //pic14_emitcode("mov","a,(%s+%d)",
2341             //         regspic14[i].base,8*bank+regspic14[i].offset);
2342             pic14_emitcode("movx","@%s,a",r->name);           
2343         } else 
2344           pic14_emitcode("push","");// "(%s+%d)",
2345                      //regspic14[i].base,8*bank+regspic14[i].offset);
2346     }
2347     
2348     if (pushPsw) {
2349         if (options.useXstack) {
2350             pic14_emitcode("mov","a,psw");
2351             pic14_emitcode("movx","@%s,a",r->name);     
2352             pic14_emitcode("inc","%s",r->name);
2353             pic14_emitcode("mov","_spx,%s",r->name);       
2354             freeAsmop (NULL,aop,ic,TRUE);
2355             
2356         } else
2357             pic14_emitcode("push","psw");
2358         
2359         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2360     }
2361     ic->bankSaved = 1;
2362 #endif
2363 }
2364
2365 /*-----------------------------------------------------------------*/
2366 /* genCall - generates a call statement                            */
2367 /*-----------------------------------------------------------------*/
2368 static void genCall (iCode *ic)
2369 {
2370   sym_link *dtype;   
2371
2372   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2373
2374   /* if caller saves & we have not saved then */
2375   if (!ic->regsSaved)
2376     saveRegisters(ic);
2377
2378   /* if we are calling a function that is not using
2379      the same register bank then we need to save the
2380      destination registers on the stack */
2381   dtype = operandType(IC_LEFT(ic));
2382   if (currFunc && dtype && 
2383       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2384       IFFUNC_ISISR(currFunc->type) &&
2385       !ic->bankSaved) 
2386
2387     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2388
2389   /* if send set is not empty the assign */
2390   if (_G.sendSet) {
2391     iCode *sic;
2392     /* For the Pic port, there is no data stack.
2393      * So parameters passed to functions are stored
2394      * in registers. (The pCode optimizer will get
2395      * rid of most of these :).
2396      */
2397     int psuedoStkPtr=-1; 
2398     int firstTimeThruLoop = 1;
2399
2400     _G.sendSet = reverseSet(_G.sendSet);
2401
2402     /* First figure how many parameters are getting passed */
2403     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2404          sic = setNextItem(_G.sendSet)) {
2405
2406       aopOp(IC_LEFT(sic),sic,FALSE);
2407       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2408       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2409     }
2410
2411     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2412          sic = setNextItem(_G.sendSet)) {
2413       int size, offset = 0;
2414
2415       aopOp(IC_LEFT(sic),sic,FALSE);
2416       size = AOP_SIZE(IC_LEFT(sic));
2417
2418       while (size--) {
2419         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2420                              AopType(AOP_TYPE(IC_LEFT(sic))));
2421
2422         if(!firstTimeThruLoop) {
2423           /* If this is not the first time we've been through the loop
2424            * then we need to save the parameter in a temporary
2425            * register. The last byte of the last parameter is
2426            * passed in W. */
2427           emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr));
2428
2429         }
2430         firstTimeThruLoop=0;
2431
2432         //if (strcmp(l,fReturn[offset])) {
2433         mov2w (AOP(IC_LEFT(sic)),  offset);
2434 /*
2435         if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
2436              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2437           emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset));
2438         else
2439           emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset));
2440 */
2441         //}
2442         offset++;
2443       }
2444       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2445     }
2446     _G.sendSet = NULL;
2447   }
2448   /* make the call */
2449   emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2450                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2451                                       OP_SYMBOL(IC_LEFT(ic))->name));
2452
2453   GpsuedoStkPtr=0;
2454   /* if we need assign a result value */
2455   if ((IS_ITEMP(IC_RESULT(ic)) && 
2456        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2457         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2458       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2459
2460     _G.accInUse++;
2461     aopOp(IC_RESULT(ic),ic,FALSE);
2462     _G.accInUse--;
2463
2464     assignResultValue(IC_RESULT(ic));
2465
2466     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2467                          AopType(AOP_TYPE(IC_RESULT(ic))));
2468                 
2469     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2470   }
2471
2472   /* adjust the stack for parameters if 
2473      required */
2474   if (ic->parmBytes) {
2475     int i;
2476     if (ic->parmBytes > 3) {
2477       pic14_emitcode("mov","a,%s",spname);
2478       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2479       pic14_emitcode("mov","%s,a",spname);
2480     } else 
2481       for ( i = 0 ; i <  ic->parmBytes ;i++)
2482         pic14_emitcode("dec","%s",spname);
2483
2484   }
2485
2486   /* if register bank was saved then pop them */
2487   if (ic->bankSaved)
2488     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2489
2490   /* if we hade saved some registers then unsave them */
2491   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2492     unsaveRegisters (ic);
2493
2494
2495 }
2496
2497 /*-----------------------------------------------------------------*/
2498 /* genPcall - generates a call by pointer statement                */
2499 /*-----------------------------------------------------------------*/
2500 static void genPcall (iCode *ic)
2501 {
2502     sym_link *dtype;
2503     symbol *albl = newiTempLabel(NULL);
2504     symbol *blbl = newiTempLabel(NULL);
2505     PIC_OPCODE poc;
2506     operand *left;
2507
2508     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2509     /* if caller saves & we have not saved then */
2510     if (!ic->regsSaved)
2511         saveRegisters(ic);
2512
2513     /* if we are calling a function that is not using
2514     the same register bank then we need to save the
2515     destination registers on the stack */
2516     dtype = operandType(IC_LEFT(ic));
2517     if (currFunc && dtype && 
2518         IFFUNC_ISISR(currFunc->type) &&
2519         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2520         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2521
2522     left = IC_LEFT(ic);
2523     aopOp(left,ic,FALSE);
2524     DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2525
2526     pushSide(IC_LEFT(ic), FPTRSIZE);
2527
2528     /* if send set is not empty, assign parameters */
2529     if (_G.sendSet) {
2530
2531         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2532         /* no way to pass args - W always gets used to make the call */
2533     }
2534 /* first idea - factor out a common helper function and call it.
2535    But don't know how to get it generated only once in its own block
2536
2537     if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2538             char *rname;
2539             char *buffer;
2540             rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2541             DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2542             buffer = Safe_calloc(1,strlen(rname)+16);
2543             sprintf(buffer, "%s_goto_helper", rname);
2544             addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2545             free(buffer);
2546     }
2547 */
2548     emitpcode(POC_CALL,popGetLabel(albl->key));
2549     emitpcode(POC_GOTO,popGetLabel(blbl->key));
2550     emitpLabel(albl->key);
2551
2552     poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
2553     
2554     emitpcode(poc,popGet(AOP(left),1));
2555     emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2556     emitpcode(poc,popGet(AOP(left),0));
2557     emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2558
2559     emitpLabel(blbl->key);
2560
2561     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2562
2563     /* if we need to assign a result value */
2564     if ((IS_ITEMP(IC_RESULT(ic)) &&
2565          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2566           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2567         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2568
2569         _G.accInUse++;
2570         aopOp(IC_RESULT(ic),ic,FALSE);
2571         _G.accInUse--;
2572         
2573         assignResultValue(IC_RESULT(ic));
2574
2575         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2576     }
2577
2578     /* if register bank was saved then unsave them */
2579     if (currFunc && dtype && 
2580         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2581         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2582
2583     /* if we hade saved some registers then
2584     unsave them */
2585     if (ic->regsSaved)
2586         unsaveRegisters (ic);
2587
2588 }
2589
2590 /*-----------------------------------------------------------------*/
2591 /* resultRemat - result  is rematerializable                       */
2592 /*-----------------------------------------------------------------*/
2593 static int resultRemat (iCode *ic)
2594 {
2595   //    DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2596   if (SKIP_IC(ic) || ic->op == IFX)
2597     return 0;
2598
2599   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2600     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2601     if (sym->remat && !POINTER_SET(ic)) 
2602       return 1;
2603   }
2604
2605   return 0;
2606 }
2607
2608 #if defined(__BORLANDC__) || defined(_MSC_VER)
2609 #define STRCASECMP stricmp
2610 #else
2611 #define STRCASECMP strcasecmp
2612 #endif
2613
2614 #if 0
2615 /*-----------------------------------------------------------------*/
2616 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2617 /*-----------------------------------------------------------------*/
2618 static bool inExcludeList(char *s)
2619 {
2620   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2621     int i =0;
2622     
2623     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2624     if (options.excludeRegs[i] &&
2625     STRCASECMP(options.excludeRegs[i],"none") == 0)
2626         return FALSE ;
2627
2628     for ( i = 0 ; options.excludeRegs[i]; i++) {
2629         if (options.excludeRegs[i] &&
2630         STRCASECMP(s,options.excludeRegs[i]) == 0)
2631             return TRUE;
2632     }
2633     return FALSE ;
2634 }
2635 #endif
2636
2637 /*-----------------------------------------------------------------*/
2638 /* genFunction - generated code for function entry                 */
2639 /*-----------------------------------------------------------------*/
2640 static void genFunction (iCode *ic)
2641 {
2642     symbol *sym;
2643     sym_link *ftype;
2644
2645     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2646
2647     labelOffset += (max_key+4);
2648     max_key=0;
2649     GpsuedoStkPtr=0;
2650     _G.nRegsSaved = 0;
2651     /* create the function header */
2652     pic14_emitcode(";","-----------------------------------------");
2653     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2654     pic14_emitcode(";","-----------------------------------------");
2655
2656     pic14_emitcode("","%s:",sym->rname);
2657     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2658
2659     ftype = operandType(IC_LEFT(ic));
2660
2661     /* if critical function then turn interrupts off */
2662     if (IFFUNC_ISCRITICAL(ftype))
2663         pic14_emitcode("clr","ea");
2664
2665     /* here we need to generate the equates for the
2666        register bank if required */
2667 #if 0
2668     if (FUNC_REGBANK(ftype) != rbank) {
2669         int i ;
2670
2671         rbank = FUNC_REGBANK(ftype);
2672         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2673             if (strcmp(regspic14[i].base,"0") == 0)
2674                 pic14_emitcode("","%s = 0x%02x",
2675                          regspic14[i].dname,
2676                          8*rbank+regspic14[i].offset);
2677             else
2678                 pic14_emitcode ("","%s = %s + 0x%02x",
2679                           regspic14[i].dname,
2680                           regspic14[i].base,
2681                           8*rbank+regspic14[i].offset);
2682         }
2683     }
2684 #endif
2685
2686     /* if this is an interrupt service routine then
2687     save acc, b, dpl, dph  */
2688     if (IFFUNC_ISISR(sym->type)) {
2689       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2690       emitpcodeNULLop(POC_NOP);
2691       emitpcodeNULLop(POC_NOP);
2692       emitpcodeNULLop(POC_NOP);
2693       emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2694       emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2695       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2696       emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2697
2698       pBlockConvert2ISR(pb);
2699 #if 0  
2700         if (!inExcludeList("acc"))          
2701             pic14_emitcode ("push","acc");      
2702         if (!inExcludeList("b"))
2703             pic14_emitcode ("push","b");
2704         if (!inExcludeList("dpl"))
2705             pic14_emitcode ("push","dpl");
2706         if (!inExcludeList("dph"))
2707             pic14_emitcode ("push","dph");
2708         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2709         {
2710             pic14_emitcode ("push", "dpx");
2711             /* Make sure we're using standard DPTR */
2712             pic14_emitcode ("push", "dps");
2713             pic14_emitcode ("mov", "dps, #0x00");
2714             if (options.stack10bit)
2715             {   
2716                 /* This ISR could conceivably use DPTR2. Better save it. */
2717                 pic14_emitcode ("push", "dpl1");
2718                 pic14_emitcode ("push", "dph1");
2719                 pic14_emitcode ("push", "dpx1");
2720             }
2721         }
2722         /* if this isr has no bank i.e. is going to
2723            run with bank 0 , then we need to save more
2724            registers :-) */
2725         if (!FUNC_REGBANK(sym->type)) {
2726
2727             /* if this function does not call any other
2728                function then we can be economical and
2729                save only those registers that are used */
2730             if (! IFFUNC_HASFCALL(sym->type)) {
2731                 int i;
2732
2733                 /* if any registers used */
2734                 if (sym->regsUsed) {
2735                     /* save the registers used */
2736                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2737                         if (bitVectBitValue(sym->regsUsed,i) ||
2738                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2739                           pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);                         
2740                     }
2741                 }
2742                 
2743             } else {
2744                 /* this function has  a function call cannot
2745                    determines register usage so we will have the
2746                    entire bank */
2747                 saverbank(0,ic,FALSE);
2748             }       
2749         }
2750 #endif
2751     } else {
2752         /* if callee-save to be used for this function
2753            then save the registers being used in this function */
2754         if (IFFUNC_CALLEESAVES(sym->type)) {
2755             int i;
2756             
2757             /* if any registers used */
2758             if (sym->regsUsed) {
2759                 /* save the registers used */
2760                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2761                     if (bitVectBitValue(sym->regsUsed,i) ||
2762                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2763                       //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2764                         _G.nRegsSaved++;
2765                     }
2766                 }
2767             }
2768         }
2769     }
2770
2771     /* set the register bank to the desired value */
2772     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2773         pic14_emitcode("push","psw");
2774         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2775     }
2776
2777     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2778
2779         if (options.useXstack) {
2780             pic14_emitcode("mov","r0,%s",spname);
2781             pic14_emitcode("mov","a,_bp");
2782             pic14_emitcode("movx","@r0,a");
2783             pic14_emitcode("inc","%s",spname);
2784         }
2785         else
2786         {
2787             /* set up the stack */
2788             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2789         }
2790         pic14_emitcode ("mov","_bp,%s",spname);
2791     }
2792
2793     /* adjust the stack for the function */
2794     if (sym->stack) {
2795
2796         int i = sym->stack;
2797         if (i > 256 ) 
2798             werror(W_STACK_OVERFLOW,sym->name);
2799
2800         if (i > 3 && sym->recvSize < 4) {              
2801
2802             pic14_emitcode ("mov","a,sp");
2803             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2804             pic14_emitcode ("mov","sp,a");
2805            
2806         }
2807         else
2808             while(i--)
2809                 pic14_emitcode("inc","sp");
2810     }
2811
2812      if (sym->xstack) {
2813
2814         pic14_emitcode ("mov","a,_spx");
2815         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2816         pic14_emitcode ("mov","_spx,a");
2817     }    
2818
2819 }
2820
2821 /*-----------------------------------------------------------------*/
2822 /* genEndFunction - generates epilogue for functions               */
2823 /*-----------------------------------------------------------------*/
2824 static void genEndFunction (iCode *ic)
2825 {
2826     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2827
2828     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2829
2830     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2831     {
2832         pic14_emitcode ("mov","%s,_bp",spname);
2833     }
2834
2835     /* if use external stack but some variables were
2836     added to the local stack then decrement the
2837     local stack */
2838     if (options.useXstack && sym->stack) {      
2839         pic14_emitcode("mov","a,sp");
2840         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2841         pic14_emitcode("mov","sp,a");
2842     }
2843
2844
2845     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2846         if (options.useXstack) {
2847             pic14_emitcode("mov","r0,%s",spname);
2848             pic14_emitcode("movx","a,@r0");
2849             pic14_emitcode("mov","_bp,a");
2850             pic14_emitcode("dec","%s",spname);
2851         }
2852         else
2853         {
2854             pic14_emitcode ("pop","_bp");
2855         }
2856     }
2857
2858     /* restore the register bank  */    
2859     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2860         pic14_emitcode ("pop","psw");
2861
2862     if (IFFUNC_ISISR(sym->type)) {
2863
2864         /* now we need to restore the registers */
2865         /* if this isr has no bank i.e. is going to
2866            run with bank 0 , then we need to save more
2867            registers :-) */
2868         if (!FUNC_REGBANK(sym->type)) {
2869             
2870             /* if this function does not call any other
2871                function then we can be economical and
2872                save only those registers that are used */
2873             if (! IFFUNC_HASFCALL(sym->type)) {
2874                 int i;
2875                 
2876                 /* if any registers used */
2877                 if (sym->regsUsed) {
2878                     /* save the registers used */
2879                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2880                         if (bitVectBitValue(sym->regsUsed,i) ||
2881                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2882                           pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2883                     }
2884                 }
2885                 
2886             } else {
2887                 /* this function has  a function call cannot
2888                    determines register usage so we will have the
2889                    entire bank */
2890                 unsaverbank(0,ic,FALSE);
2891             }       
2892         }
2893 #if 0
2894         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2895         {
2896             if (options.stack10bit)
2897             {
2898                 pic14_emitcode ("pop", "dpx1");
2899                 pic14_emitcode ("pop", "dph1");
2900                 pic14_emitcode ("pop", "dpl1");
2901             }   
2902             pic14_emitcode ("pop", "dps");
2903             pic14_emitcode ("pop", "dpx");
2904         }
2905         if (!inExcludeList("dph"))
2906             pic14_emitcode ("pop","dph");
2907         if (!inExcludeList("dpl"))
2908             pic14_emitcode ("pop","dpl");
2909         if (!inExcludeList("b"))
2910             pic14_emitcode ("pop","b");
2911         if (!inExcludeList("acc"))
2912             pic14_emitcode ("pop","acc");
2913
2914         if (IFFUNC_ISCRITICAL(sym->type))
2915             pic14_emitcode("setb","ea");
2916 #endif
2917
2918         /* if debug then send end of function */
2919 /*      if (options.debug && currFunc) { */
2920         if (currFunc) {
2921             _G.debugLine = 1;
2922             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2923                      FileBaseName(ic->filename),currFunc->lastLine,
2924                      ic->level,ic->block); 
2925             if (IS_STATIC(currFunc->etype))         
2926                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2927             else
2928                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2929             _G.debugLine = 0;
2930         }
2931         
2932         pic14_emitcode ("reti","");
2933
2934         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2935         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2936         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2937         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2938         emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2939         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2940
2941         emitpcodeNULLop(POC_RETFIE);
2942
2943     }
2944     else {
2945         if (IFFUNC_ISCRITICAL(sym->type))
2946             pic14_emitcode("setb","ea");
2947         
2948         if (IFFUNC_CALLEESAVES(sym->type)) {
2949             int i;
2950             
2951             /* if any registers used */
2952             if (sym->regsUsed) {
2953                 /* save the registers used */
2954                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2955                     if (bitVectBitValue(sym->regsUsed,i) ||
2956                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2957                       pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2958                 }
2959             }
2960             
2961         }
2962
2963         /* if debug then send end of function */
2964         if (currFunc) {
2965             _G.debugLine = 1;
2966             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2967                      FileBaseName(ic->filename),currFunc->lastLine,
2968                      ic->level,ic->block); 
2969             if (IS_STATIC(currFunc->etype))         
2970                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2971             else
2972                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2973             _G.debugLine = 0;
2974         }
2975
2976         pic14_emitcode ("return","");
2977         emitpcodeNULLop(POC_RETURN);
2978
2979         /* Mark the end of a function */
2980         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2981     }
2982
2983 }
2984
2985 /*-----------------------------------------------------------------*/
2986 /* genRet - generate code for return statement                     */
2987 /*-----------------------------------------------------------------*/
2988 static void genRet (iCode *ic)
2989 {
2990   int size,offset = 0 , pushed = 0;
2991     
2992   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2993   /* if we have no return value then
2994      just generate the "ret" */
2995   if (!IC_LEFT(ic)) 
2996     goto jumpret;       
2997     
2998   /* we have something to return then
2999      move the return value into place */
3000   aopOp(IC_LEFT(ic),ic,FALSE);
3001   size = AOP_SIZE(IC_LEFT(ic));
3002     
3003   while (size--) {
3004     char *l ;
3005     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3006       /* #NOCHANGE */
3007       l = aopGet(AOP(IC_LEFT(ic)),offset++,
3008                  FALSE,TRUE);
3009       pic14_emitcode("push","%s",l);
3010       pushed++;
3011     } else {
3012       l = aopGet(AOP(IC_LEFT(ic)),offset,
3013                  FALSE,FALSE);
3014       if (strcmp(fReturn[offset],l)) {
3015       if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
3016            AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
3017           ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3018           ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3019           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
3020         }else {
3021           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3022         }
3023         if(size) {
3024           emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
3025         }
3026         offset++;
3027       }
3028     }
3029   }    
3030
3031   if (pushed) {
3032     while(pushed) {
3033       pushed--;
3034       if (strcmp(fReturn[pushed],"a"))
3035         pic14_emitcode("pop",fReturn[pushed]);
3036       else
3037         pic14_emitcode("pop","acc");
3038     }
3039   }
3040   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3041     
3042  jumpret:
3043   /* generate a jump to the return label
3044      if the next is not the return statement */
3045   if (!(ic->next && ic->next->op == LABEL &&
3046         IC_LABEL(ic->next) == returnLabel)) {
3047         
3048     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3049     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3050   }
3051     
3052 }
3053
3054 /*-----------------------------------------------------------------*/
3055 /* genLabel - generates a label                                    */
3056 /*-----------------------------------------------------------------*/
3057 static void genLabel (iCode *ic)
3058 {
3059     /* special case never generate */
3060     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3061     if (IC_LABEL(ic) == entryLabel)
3062         return ;
3063
3064     emitpLabel(IC_LABEL(ic)->key);
3065     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3066 }
3067
3068 /*-----------------------------------------------------------------*/
3069 /* genGoto - generates a goto                                      */
3070 /*-----------------------------------------------------------------*/
3071 //tsd
3072 static void genGoto (iCode *ic)
3073 {
3074   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3075   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3076 }
3077
3078
3079 /*-----------------------------------------------------------------*/
3080 /* genMultbits :- multiplication of bits                           */
3081 /*-----------------------------------------------------------------*/
3082 static void genMultbits (operand *left, 
3083                          operand *right, 
3084                          operand *result)
3085 {
3086   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3087
3088   if(!pic14_sameRegs(AOP(result),AOP(right)))
3089     emitpcode(POC_BSF,  popGet(AOP(result),0));
3090
3091   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3092   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3093   emitpcode(POC_BCF,  popGet(AOP(result),0));
3094
3095 }
3096
3097
3098 /*-----------------------------------------------------------------*/
3099 /* genMultOneByte : 8 bit multiplication & division                */
3100 /*-----------------------------------------------------------------*/
3101 static void genMultOneByte (operand *left,
3102                             operand *right,
3103                             operand *result)
3104 {
3105   sym_link *opetype = operandType(result);
3106
3107   // symbol *lbl ;
3108   int size,offset;
3109
3110   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3111   DEBUGpic14_AopType(__LINE__,left,right,result);
3112   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3113
3114   /* (if two literals, the value is computed before) */
3115   /* if one literal, literal on the right */
3116   if (AOP_TYPE(left) == AOP_LIT){
3117     operand *t = right;
3118     right = left;
3119     left = t;
3120   }
3121
3122   size = AOP_SIZE(result);
3123   if(size == 1) {
3124
3125     if (AOP_TYPE(right) == AOP_LIT){
3126       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3127                      aopGet(AOP(right),0,FALSE,FALSE), 
3128                      aopGet(AOP(left),0,FALSE,FALSE), 
3129                      aopGet(AOP(result),0,FALSE,FALSE));
3130       pic14_emitcode("call","genMultLit");
3131     } else {
3132       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3133                      aopGet(AOP(right),0,FALSE,FALSE), 
3134                      aopGet(AOP(left),0,FALSE,FALSE), 
3135                      aopGet(AOP(result),0,FALSE,FALSE));
3136       pic14_emitcode("call","genMult8X8_8");
3137
3138     }
3139     genMult8X8_8 (left, right,result);
3140
3141
3142     /* signed or unsigned */
3143     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3144     //l = aopGet(AOP(left),0,FALSE,FALSE);
3145     //MOVA(l);       
3146     //pic14_emitcode("mul","ab");
3147     /* if result size = 1, mul signed = mul unsigned */
3148     //aopPut(AOP(result),"a",0);
3149
3150   } else {  // (size > 1)
3151
3152     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3153                    aopGet(AOP(right),0,FALSE,FALSE), 
3154                    aopGet(AOP(left),0,FALSE,FALSE), 
3155                    aopGet(AOP(result),0,FALSE,FALSE));
3156
3157     if (SPEC_USIGN(opetype)){
3158       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3159       genUMult8X8_16 (left, right, result, NULL);
3160
3161       if (size > 2) {
3162         /* for filling the MSBs */
3163         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3164         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3165       }
3166     }
3167     else{
3168       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3169
3170       pic14_emitcode("mov","a,b");
3171
3172       /* adjust the MSB if left or right neg */
3173
3174       /* if one literal */
3175       if (AOP_TYPE(right) == AOP_LIT){
3176         pic14_emitcode("multiply ","right is a lit");
3177         /* AND literal negative */
3178         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3179           /* adjust MSB (c==0 after mul) */
3180           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3181         }
3182       }
3183       else{
3184         genSMult8X8_16 (left, right, result, NULL);
3185       }
3186
3187       if(size > 2){
3188         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3189         /* get the sign */
3190         pic14_emitcode("rlc","a");
3191         pic14_emitcode("subb","a,acc");
3192       }
3193     }
3194
3195     size -= 2;   
3196     offset = 2;
3197     if (size > 0)
3198       while (size--)
3199         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3200     //aopPut(AOP(result),"a",offset++);
3201   }
3202 }
3203
3204 /*-----------------------------------------------------------------*/
3205 /* genMult - generates code for multiplication                     */
3206 /*-----------------------------------------------------------------*/
3207 static void genMult (iCode *ic)
3208 {
3209     operand *left = IC_LEFT(ic);
3210     operand *right = IC_RIGHT(ic);
3211     operand *result= IC_RESULT(ic);   
3212
3213     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3214     /* assign the amsops */
3215     aopOp (left,ic,FALSE);
3216     aopOp (right,ic,FALSE);
3217     aopOp (result,ic,TRUE);
3218
3219   DEBUGpic14_AopType(__LINE__,left,right,result);
3220
3221     /* special cases first */
3222     /* both are bits */
3223     if (AOP_TYPE(left) == AOP_CRY &&
3224         AOP_TYPE(right)== AOP_CRY) {
3225         genMultbits(left,right,result);
3226         goto release ;
3227     }
3228
3229     /* if both are of size == 1 */
3230     if (AOP_SIZE(left) == 1 &&
3231         AOP_SIZE(right) == 1 ) {
3232         genMultOneByte(left,right,result);
3233         goto release ;
3234     }
3235
3236     pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3237
3238     /* should have been converted to function call */
3239     //assert(0) ;
3240
3241 release :
3242     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3243     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3244     freeAsmop(result,NULL,ic,TRUE); 
3245 }
3246
3247 /*-----------------------------------------------------------------*/
3248 /* genDivbits :- division of bits                                  */
3249 /*-----------------------------------------------------------------*/
3250 static void genDivbits (operand *left, 
3251                         operand *right, 
3252                         operand *result)
3253 {
3254
3255     char *l;
3256
3257     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3258     /* the result must be bit */    
3259     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3260     l = aopGet(AOP(left),0,FALSE,FALSE);
3261
3262     MOVA(l);    
3263
3264     pic14_emitcode("div","ab");
3265     pic14_emitcode("rrc","a");
3266     aopPut(AOP(result),"c",0);
3267 }
3268
3269 /*-----------------------------------------------------------------*/
3270 /* genDivOneByte : 8 bit division                                  */
3271 /*-----------------------------------------------------------------*/
3272 static void genDivOneByte (operand *left,
3273                            operand *right,
3274                            operand *result)
3275 {
3276     sym_link *opetype = operandType(result);
3277     char *l ;
3278     symbol *lbl ;
3279     int size,offset;
3280
3281     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3282     size = AOP_SIZE(result) - 1;
3283     offset = 1;
3284     /* signed or unsigned */
3285     if (SPEC_USIGN(opetype)) {
3286         /* unsigned is easy */
3287         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3288         l = aopGet(AOP(left),0,FALSE,FALSE);
3289         MOVA(l);        
3290         pic14_emitcode("div","ab");
3291         aopPut(AOP(result),"a",0);
3292         while (size--)
3293             aopPut(AOP(result),zero,offset++);
3294         return ;
3295     }
3296
3297     /* signed is a little bit more difficult */
3298
3299     /* save the signs of the operands */
3300     l = aopGet(AOP(left),0,FALSE,FALSE);    
3301     MOVA(l);    
3302     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3303     pic14_emitcode("push","acc"); /* save it on the stack */
3304
3305     /* now sign adjust for both left & right */
3306     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3307     MOVA(l);       
3308     lbl = newiTempLabel(NULL);
3309     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3310     pic14_emitcode("cpl","a");   
3311     pic14_emitcode("inc","a");
3312     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3313     pic14_emitcode("mov","b,a");
3314
3315     /* sign adjust left side */
3316     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3317     MOVA(l);
3318
3319     lbl = newiTempLabel(NULL);
3320     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3321     pic14_emitcode("cpl","a");
3322     pic14_emitcode("inc","a");
3323     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3324
3325     /* now the division */
3326     pic14_emitcode("div","ab");
3327     /* we are interested in the lower order
3328     only */
3329     pic14_emitcode("mov","b,a");
3330     lbl = newiTempLabel(NULL);
3331     pic14_emitcode("pop","acc");   
3332     /* if there was an over flow we don't 
3333     adjust the sign of the result */
3334     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3335     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3336     CLRC;
3337     pic14_emitcode("clr","a");
3338     pic14_emitcode("subb","a,b");
3339     pic14_emitcode("mov","b,a");
3340     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3341
3342     /* now we are done */
3343     aopPut(AOP(result),"b",0);
3344     if(size > 0){
3345         pic14_emitcode("mov","c,b.7");
3346         pic14_emitcode("subb","a,acc");   
3347     }
3348     while (size--)
3349         aopPut(AOP(result),"a",offset++);
3350
3351 }
3352
3353 /*-----------------------------------------------------------------*/
3354 /* genDiv - generates code for division                            */
3355 /*-----------------------------------------------------------------*/
3356 static void genDiv (iCode *ic)
3357 {
3358     operand *left = IC_LEFT(ic);
3359     operand *right = IC_RIGHT(ic);
3360     operand *result= IC_RESULT(ic);   
3361
3362     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3363     /* assign the amsops */
3364     aopOp (left,ic,FALSE);
3365     aopOp (right,ic,FALSE);
3366     aopOp (result,ic,TRUE);
3367
3368     /* special cases first */
3369     /* both are bits */
3370     if (AOP_TYPE(left) == AOP_CRY &&
3371         AOP_TYPE(right)== AOP_CRY) {
3372         genDivbits(left,right,result);
3373         goto release ;
3374     }
3375
3376     /* if both are of size == 1 */
3377     if (AOP_SIZE(left) == 1 &&
3378         AOP_SIZE(right) == 1 ) {
3379         genDivOneByte(left,right,result);
3380         goto release ;
3381     }
3382
3383     /* should have been converted to function call */
3384     assert(0);
3385 release :
3386     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3387     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3388     freeAsmop(result,NULL,ic,TRUE); 
3389 }
3390
3391 /*-----------------------------------------------------------------*/
3392 /* genModbits :- modulus of bits                                   */
3393 /*-----------------------------------------------------------------*/
3394 static void genModbits (operand *left, 
3395                         operand *right, 
3396                         operand *result)
3397 {
3398
3399     char *l;
3400
3401     /* the result must be bit */    
3402     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3403     l = aopGet(AOP(left),0,FALSE,FALSE);
3404
3405     MOVA(l);       
3406
3407     pic14_emitcode("div","ab");
3408     pic14_emitcode("mov","a,b");
3409     pic14_emitcode("rrc","a");
3410     aopPut(AOP(result),"c",0);
3411 }
3412
3413 /*-----------------------------------------------------------------*/
3414 /* genModOneByte : 8 bit modulus                                   */
3415 /*-----------------------------------------------------------------*/
3416 static void genModOneByte (operand *left,
3417                            operand *right,
3418                            operand *result)
3419 {
3420     sym_link *opetype = operandType(result);
3421     char *l ;
3422     symbol *lbl ;
3423
3424     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3425     /* signed or unsigned */
3426     if (SPEC_USIGN(opetype)) {
3427         /* unsigned is easy */
3428         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3429         l = aopGet(AOP(left),0,FALSE,FALSE);
3430         MOVA(l);    
3431         pic14_emitcode("div","ab");
3432         aopPut(AOP(result),"b",0);
3433         return ;
3434     }
3435
3436     /* signed is a little bit more difficult */
3437
3438     /* save the signs of the operands */
3439     l = aopGet(AOP(left),0,FALSE,FALSE);    
3440     MOVA(l);
3441
3442     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3443     pic14_emitcode("push","acc"); /* save it on the stack */
3444
3445     /* now sign adjust for both left & right */
3446     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3447     MOVA(l);
3448
3449     lbl = newiTempLabel(NULL);
3450     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3451     pic14_emitcode("cpl","a");   
3452     pic14_emitcode("inc","a");
3453     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3454     pic14_emitcode("mov","b,a"); 
3455
3456     /* sign adjust left side */
3457     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3458     MOVA(l);
3459
3460     lbl = newiTempLabel(NULL);
3461     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3462     pic14_emitcode("cpl","a");   
3463     pic14_emitcode("inc","a");
3464     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3465
3466     /* now the multiplication */
3467     pic14_emitcode("div","ab");
3468     /* we are interested in the lower order
3469     only */
3470     lbl = newiTempLabel(NULL);
3471     pic14_emitcode("pop","acc");   
3472     /* if there was an over flow we don't 
3473     adjust the sign of the result */
3474     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3475     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3476     CLRC ;
3477     pic14_emitcode("clr","a");
3478     pic14_emitcode("subb","a,b");
3479     pic14_emitcode("mov","b,a");
3480     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3481
3482     /* now we are done */
3483     aopPut(AOP(result),"b",0);
3484
3485 }
3486
3487 /*-----------------------------------------------------------------*/
3488 /* genMod - generates code for division                            */
3489 /*-----------------------------------------------------------------*/
3490 static void genMod (iCode *ic)
3491 {
3492     operand *left = IC_LEFT(ic);
3493     operand *right = IC_RIGHT(ic);
3494     operand *result= IC_RESULT(ic);  
3495
3496     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3497     /* assign the amsops */
3498     aopOp (left,ic,FALSE);
3499     aopOp (right,ic,FALSE);
3500     aopOp (result,ic,TRUE);
3501
3502     /* special cases first */
3503     /* both are bits */
3504     if (AOP_TYPE(left) == AOP_CRY &&
3505         AOP_TYPE(right)== AOP_CRY) {
3506         genModbits(left,right,result);
3507         goto release ;
3508     }
3509
3510     /* if both are of size == 1 */
3511     if (AOP_SIZE(left) == 1 &&
3512         AOP_SIZE(right) == 1 ) {
3513         genModOneByte(left,right,result);
3514         goto release ;
3515     }
3516
3517     /* should have been converted to function call */
3518     assert(0);
3519
3520 release :
3521     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3522     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3523     freeAsmop(result,NULL,ic,TRUE); 
3524 }
3525
3526 /*-----------------------------------------------------------------*/
3527 /* genIfxJump :- will create a jump depending on the ifx           */
3528 /*-----------------------------------------------------------------*/
3529 /*
3530   note: May need to add parameter to indicate when a variable is in bit space.
3531 */
3532 static void genIfxJump (iCode *ic, char *jval)
3533 {
3534
3535     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3536     /* if true label then we jump if condition
3537     supplied is true */
3538     if ( IC_TRUE(ic) ) {
3539
3540         if(strcmp(jval,"a") == 0)
3541           emitSKPZ;
3542         else if (strcmp(jval,"c") == 0)
3543           emitSKPC;
3544         else {
3545           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3546           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3547         }
3548
3549         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3550         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3551
3552     }
3553     else {
3554         /* false label is present */
3555         if(strcmp(jval,"a") == 0)
3556           emitSKPNZ;
3557         else if (strcmp(jval,"c") == 0)
3558           emitSKPNC;
3559         else {
3560           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3561           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3562         }
3563
3564         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3565         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3566
3567     }
3568
3569
3570     /* mark the icode as generated */
3571     ic->generated = 1;
3572 }
3573
3574 /*-----------------------------------------------------------------*/
3575 /* genSkip                                                         */
3576 /*-----------------------------------------------------------------*/
3577 static void genSkip(iCode *ifx,int status_bit)
3578 {
3579   if(!ifx)
3580     return;
3581
3582   if ( IC_TRUE(ifx) ) {
3583     switch(status_bit) {
3584     case 'z':
3585       emitSKPNZ;
3586       break;
3587
3588     case 'c':
3589       emitSKPNC;
3590       break;
3591
3592     case 'd':
3593       emitSKPDC;
3594       break;
3595
3596     }
3597
3598     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3599     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3600
3601   } else {
3602
3603     switch(status_bit) {
3604
3605     case 'z':
3606       emitSKPZ;
3607       break;
3608
3609     case 'c':
3610       emitSKPC;
3611       break;
3612
3613     case 'd':
3614       emitSKPDC;
3615       break;
3616     }
3617     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3618     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3619
3620   }
3621
3622 }
3623
3624 /*-----------------------------------------------------------------*/
3625 /* genSkipc                                                        */
3626 /*-----------------------------------------------------------------*/
3627 static void genSkipc(resolvedIfx *rifx)
3628 {
3629   if(!rifx)
3630     return;
3631
3632   if(rifx->condition)
3633     emitSKPC;
3634   else
3635     emitSKPNC;
3636
3637   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3638   rifx->generated = 1;
3639 }
3640
3641 /*-----------------------------------------------------------------*/
3642 /* genSkipz2                                                       */
3643 /*-----------------------------------------------------------------*/
3644 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3645 {
3646   if(!rifx)
3647     return;
3648
3649   if( (rifx->condition ^ invert_condition) & 1)
3650     emitSKPZ;
3651   else
3652     emitSKPNZ;
3653
3654   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3655   rifx->generated = 1;
3656 }
3657
3658 /*-----------------------------------------------------------------*/
3659 /* genSkipz                                                        */
3660 /*-----------------------------------------------------------------*/
3661 static void genSkipz(iCode *ifx, int condition)
3662 {
3663   if(!ifx)
3664     return;
3665
3666   if(condition)
3667     emitSKPNZ;
3668   else
3669     emitSKPZ;
3670
3671   if ( IC_TRUE(ifx) )
3672     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3673   else
3674     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3675
3676   if ( IC_TRUE(ifx) )
3677     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3678   else
3679     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3680
3681 }
3682 /*-----------------------------------------------------------------*/
3683 /* genSkipCond                                                     */
3684 /*-----------------------------------------------------------------*/
3685 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3686 {
3687   if(!rifx)
3688     return;
3689
3690   if(rifx->condition)
3691     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3692   else
3693     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3694
3695
3696   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3697   rifx->generated = 1;
3698 }
3699
3700 #if 0
3701 /*-----------------------------------------------------------------*/
3702 /* genChkZeroes :- greater or less than comparison                 */
3703 /*     For each byte in a literal that is zero, inclusive or the   */
3704 /*     the corresponding byte in the operand with W                */
3705 /*     returns true if any of the bytes are zero                   */
3706 /*-----------------------------------------------------------------*/
3707 static int genChkZeroes(operand *op, int lit,  int size)
3708 {
3709
3710   int i;
3711   int flag =1;
3712
3713   while(size--) {
3714     i = (lit >> (size*8)) & 0xff;
3715
3716     if(i==0) {
3717       if(flag) 
3718         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3719       else
3720         emitpcode(POC_IORFW, popGet(AOP(op),size));
3721       flag = 0;
3722     }
3723   }
3724
3725   return (flag==0);
3726 }
3727 #endif
3728
3729 /*-----------------------------------------------------------------*/
3730 /* genCmp :- greater or less than comparison                       */
3731 /*-----------------------------------------------------------------*/
3732 static void genCmp (operand *left,operand *right,
3733                     operand *result, iCode *ifx, int sign)
3734 {
3735   int size; //, offset = 0 ;
3736   unsigned long lit = 0L,i = 0;
3737   resolvedIfx rFalseIfx;
3738   //  resolvedIfx rTrueIfx;
3739   symbol *truelbl;
3740   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3741 /*
3742   if(ifx) {
3743     DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3744     DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3745   }
3746 */
3747
3748   resolveIfx(&rFalseIfx,ifx);
3749   truelbl  = newiTempLabel(NULL);
3750   size = max(AOP_SIZE(left),AOP_SIZE(right));
3751
3752   DEBUGpic14_AopType(__LINE__,left,right,result);
3753
3754 #define _swapp
3755
3756   /* if literal is on the right then swap with left */
3757   if ((AOP_TYPE(right) == AOP_LIT)) {
3758     operand *tmp = right ;
3759     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3760     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3761 #ifdef _swapp
3762
3763     lit = (lit - 1) & mask;
3764     right = left;
3765     left = tmp;
3766     rFalseIfx.condition ^= 1;
3767 #endif
3768
3769   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3770     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3771   }
3772
3773
3774   //if(IC_TRUE(ifx) == NULL)
3775   /* if left & right are bit variables */
3776   if (AOP_TYPE(left) == AOP_CRY &&
3777       AOP_TYPE(right) == AOP_CRY ) {
3778     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3779     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3780   } else {
3781     /* subtract right from left if at the
3782        end the carry flag is set then we know that
3783        left is greater than right */
3784
3785     //    {
3786
3787     symbol *lbl  = newiTempLabel(NULL);
3788
3789 #ifndef _swapp
3790     if(AOP_TYPE(right) == AOP_LIT) {
3791
3792       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3793
3794       DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3795
3796       /* special cases */
3797
3798       if(lit == 0) {
3799
3800         if(sign != 0) 
3801           genSkipCond(&rFalseIfx,left,size-1,7);
3802         else 
3803           /* no need to compare to 0...*/
3804           /* NOTE: this is a de-generate compare that most certainly 
3805            *       creates some dead code. */
3806           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3807
3808         if(ifx) ifx->generated = 1;
3809         return;
3810
3811       }
3812       size--;
3813
3814       if(size == 0) {
3815         //i = (lit >> (size*8)) & 0xff;
3816         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3817         
3818         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3819
3820         i = ((0-lit) & 0xff);
3821         if(sign) {
3822           if( i == 0x81) { 
3823             /* lit is 0x7f, all signed chars are less than
3824              * this except for 0x7f itself */
3825             emitpcode(POC_XORLW, popGetLit(0x7f));
3826             genSkipz2(&rFalseIfx,0);
3827           } else {
3828             emitpcode(POC_ADDLW, popGetLit(0x80));
3829             emitpcode(POC_ADDLW, popGetLit(i^0x80));
3830             genSkipc(&rFalseIfx);
3831           }
3832
3833         } else {
3834           if(lit == 1) {
3835             genSkipz2(&rFalseIfx,1);
3836           } else {
3837             emitpcode(POC_ADDLW, popGetLit(i));
3838             genSkipc(&rFalseIfx);
3839           }
3840         }
3841
3842         if(ifx) ifx->generated = 1;
3843         return;
3844       }
3845
3846       /* chars are out of the way. now do ints and longs */
3847
3848
3849       DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3850         
3851       /* special cases */
3852
3853       if(sign) {
3854
3855         if(lit == 0) {
3856           genSkipCond(&rFalseIfx,left,size,7);
3857           if(ifx) ifx->generated = 1;
3858           return;
3859         }
3860
3861         if(lit <0x100) {
3862           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3863
3864           //rFalseIfx.condition ^= 1;
3865           //genSkipCond(&rFalseIfx,left,size,7);
3866           //rFalseIfx.condition ^= 1;
3867
3868           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3869           if(rFalseIfx.condition)
3870             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3871           else
3872             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3873
3874           emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3875           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3876           emitpcode(POC_MOVFW, popGet(AOP(left),1));
3877
3878           while(size > 1)
3879             emitpcode(POC_IORFW, popGet(AOP(left),size--));
3880
3881           if(rFalseIfx.condition) {
3882             emitSKPZ;
3883             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3884
3885           } else {
3886             emitSKPNZ;
3887           }
3888
3889           genSkipc(&rFalseIfx);
3890           emitpLabel(truelbl->key);
3891           if(ifx) ifx->generated = 1;
3892           return;
3893
3894         }
3895
3896         if(size == 1) {
3897
3898           if( (lit & 0xff) == 0) {
3899             /* lower byte is zero */
3900             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3901             i = ((lit >> 8) & 0xff) ^0x80;
3902             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3903             emitpcode(POC_ADDLW, popGetLit( 0x80));
3904             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3905             genSkipc(&rFalseIfx);
3906
3907
3908             if(ifx) ifx->generated = 1;
3909             return;
3910
3911           }
3912         } else {
3913           /* Special cases for signed longs */
3914           if( (lit & 0xffffff) == 0) {
3915             /* lower byte is zero */
3916             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3917             i = ((lit >> 8*3) & 0xff) ^0x80;
3918             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3919             emitpcode(POC_ADDLW, popGetLit( 0x80));
3920             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3921             genSkipc(&rFalseIfx);
3922
3923
3924             if(ifx) ifx->generated = 1;
3925             return;
3926
3927           }
3928
3929         }
3930
3931
3932         if(lit & (0x80 << (size*8))) {
3933           /* lit is negative */
3934           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3935
3936           //genSkipCond(&rFalseIfx,left,size,7);
3937
3938           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3939
3940           if(rFalseIfx.condition)
3941             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3942           else
3943             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3944
3945
3946         } else {
3947           /* lit is positive */
3948           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3949           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3950           if(rFalseIfx.condition)
3951             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3952           else
3953             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3954
3955         }
3956
3957         /*
3958           This works, but is only good for ints.
3959           It also requires a "known zero" register.
3960           emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3961           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3962           emitpcode(POC_RLFW,  popCopyReg(&pc_kzero));
3963           emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
3964           emitpcode(POC_ADDFW, popGet(AOP(left),1));
3965           genSkipc(&rFalseIfx);
3966
3967           emitpLabel(truelbl->key);
3968           if(ifx) ifx->generated = 1;
3969           return;
3970         **/
3971           
3972         /* There are no more special cases, so perform a general compare */
3973   
3974         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3975         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3976
3977         while(size--) {
3978
3979           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3980           emitSKPNZ;
3981           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3982         }
3983         //rFalseIfx.condition ^= 1;
3984         genSkipc(&rFalseIfx);
3985
3986         emitpLabel(truelbl->key);
3987
3988         if(ifx) ifx->generated = 1;
3989         return;
3990
3991
3992       }
3993
3994
3995       /* sign is out of the way. So now do an unsigned compare */
3996       DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3997
3998
3999       /* General case - compare to an unsigned literal on the right.*/
4000
4001       i = (lit >> (size*8)) & 0xff;
4002       emitpcode(POC_MOVLW, popGetLit(i));
4003       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4004       while(size--) {
4005         i = (lit >> (size*8)) & 0xff;
4006
4007         if(i) {
4008           emitpcode(POC_MOVLW, popGetLit(i));
4009           emitSKPNZ;
4010           emitpcode(POC_SUBFW, popGet(AOP(left),size));
4011         } else {
4012           /* this byte of the lit is zero, 
4013            *if it's not the last then OR in the variable */
4014           if(size)
4015             emitpcode(POC_IORFW, popGet(AOP(left),size));
4016         }
4017       }
4018
4019
4020       emitpLabel(lbl->key);
4021       //if(emitFinalCheck)
4022       genSkipc(&rFalseIfx);
4023       if(sign)
4024         emitpLabel(truelbl->key);
4025
4026       if(ifx) ifx->generated = 1;
4027       return;
4028
4029
4030     }
4031 #endif  // _swapp
4032
4033     if(AOP_TYPE(left) == AOP_LIT) {
4034       //symbol *lbl = newiTempLabel(NULL);
4035
4036       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4037
4038
4039       DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4040
4041       /* Special cases */
4042       if((lit == 0) && (sign == 0)){
4043
4044         size--;
4045         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4046         while(size) 
4047           emitpcode(POC_IORFW, popGet(AOP(right),--size));
4048
4049         genSkipz2(&rFalseIfx,0);
4050         if(ifx) ifx->generated = 1;
4051         return;
4052       }
4053
4054       if(size==1) {
4055         /* Special cases */
4056         lit &= 0xff;
4057         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4058           /* degenerate compare can never be true */
4059           if(rFalseIfx.condition == 0)
4060             emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4061
4062           if(ifx) ifx->generated = 1;
4063           return;
4064         }
4065
4066         if(sign) {
4067           /* signed comparisons to a literal byte */
4068
4069           int lp1 = (lit+1) & 0xff;
4070
4071           DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4072           switch (lp1) {
4073           case 0:
4074             rFalseIfx.condition ^= 1;
4075             genSkipCond(&rFalseIfx,right,0,7);
4076             break;
4077           case 0x7f:
4078             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4079             emitpcode(POC_XORLW, popGetLit(0x7f));
4080             genSkipz2(&rFalseIfx,1);
4081             break;
4082           default:
4083             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4084             emitpcode(POC_ADDLW, popGetLit(0x80));
4085             emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4086             rFalseIfx.condition ^= 1;
4087             genSkipc(&rFalseIfx);
4088             break;
4089           }
4090           if(ifx) ifx->generated = 1;
4091         } else {
4092           /* unsigned comparisons to a literal byte */
4093
4094           switch(lit & 0xff ) {
4095           case 0:
4096             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4097             genSkipz2(&rFalseIfx,0);
4098             if(ifx) ifx->generated = 1;
4099             break;
4100           case 0x7f:
4101             rFalseIfx.condition ^= 1;
4102             genSkipCond(&rFalseIfx,right,0,7);
4103             if(ifx) ifx->generated = 1;
4104             break;
4105
4106           default:
4107             emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4108             emitpcode(POC_SUBFW, popGet(AOP(right),0));
4109             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4110             rFalseIfx.condition ^= 1;
4111             if (AOP_TYPE(result) == AOP_CRY) {
4112               genSkipc(&rFalseIfx);
4113               if(ifx) ifx->generated = 1;
4114             } else {
4115               DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4116               emitpcode(POC_CLRF, popGet(AOP(result),0));
4117               emitpcode(POC_RLF, popGet(AOP(result),0));
4118               emitpcode(POC_MOVLW, popGetLit(0x01));
4119               emitpcode(POC_XORWF, popGet(AOP(result),0));
4120             }         
4121             break;
4122           }
4123         }
4124
4125         //goto check_carry;
4126         return;
4127
4128       } else {
4129
4130         /* Size is greater than 1 */
4131
4132         if(sign) {
4133           int lp1 = lit+1;
4134
4135           size--;
4136
4137           if(lp1 == 0) {
4138             /* this means lit = 0xffffffff, or -1 */
4139
4140
4141             DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4142             rFalseIfx.condition ^= 1;
4143             genSkipCond(&rFalseIfx,right,size,7);
4144             if(ifx) ifx->generated = 1;
4145             return;
4146           }
4147
4148           if(lit == 0) {
4149             int s = size;
4150
4151             if(rFalseIfx.condition) {
4152               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4153               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4154             }
4155
4156             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4157             while(size--)
4158               emitpcode(POC_IORFW, popGet(AOP(right),size));
4159
4160
4161             emitSKPZ;
4162             if(rFalseIfx.condition) {
4163               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4164               emitpLabel(truelbl->key);
4165             }else {
4166               rFalseIfx.condition ^= 1;
4167               genSkipCond(&rFalseIfx,right,s,7);
4168             }
4169
4170             if(ifx) ifx->generated = 1;
4171             return;
4172           }
4173
4174           if((size == 1) &&  (0 == (lp1&0xff))) {
4175             /* lower byte of signed word is zero */
4176             DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4177             i = ((lp1 >> 8) & 0xff) ^0x80;
4178             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4179             emitpcode(POC_ADDLW, popGetLit( 0x80));
4180             emitpcode(POC_ADDLW, popGetLit(0x100-i));
4181             rFalseIfx.condition ^= 1;
4182             genSkipc(&rFalseIfx);
4183
4184
4185             if(ifx) ifx->generated = 1;
4186             return;
4187           }
4188
4189           if(lit & (0x80 << (size*8))) {
4190             /* Lit is less than zero */
4191             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4192             //rFalseIfx.condition ^= 1;
4193             //genSkipCond(&rFalseIfx,left,size,7);
4194             //rFalseIfx.condition ^= 1;
4195             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4196             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4197
4198             if(rFalseIfx.condition)
4199               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4200             else
4201               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4202
4203
4204           } else {
4205             /* Lit is greater than or equal to zero */
4206             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4207             //rFalseIfx.condition ^= 1;
4208             //genSkipCond(&rFalseIfx,right,size,7);
4209             //rFalseIfx.condition ^= 1;
4210
4211             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4212             //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4213
4214             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4215             if(rFalseIfx.condition)
4216               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4217             else
4218               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4219
4220           }
4221
4222
4223           emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4224           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4225
4226           while(size--) {
4227
4228             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4229             emitSKPNZ;
4230             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4231           }
4232           rFalseIfx.condition ^= 1;
4233           //rFalseIfx.condition = 1;
4234           genSkipc(&rFalseIfx);
4235
4236           emitpLabel(truelbl->key);
4237
4238           if(ifx) ifx->generated = 1;
4239           return;
4240           // end of if (sign)
4241         } else {
4242
4243           /* compare word or long to an unsigned literal on the right.*/
4244
4245
4246           size--;
4247           if(lit < 0xff) {
4248             DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4249             switch (lit) {
4250             case 0:
4251               break; /* handled above */
4252 /*
4253             case 0xff:
4254               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4255               while(size--)
4256                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4257               genSkipz2(&rFalseIfx,0);
4258               break;
4259 */
4260             default:
4261               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4262               while(--size)
4263                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4264
4265               emitSKPZ;
4266               if(rFalseIfx.condition)
4267                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4268               else
4269                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4270
4271
4272               emitpcode(POC_MOVLW, popGetLit(lit+1));
4273               emitpcode(POC_SUBFW, popGet(AOP(right),0));
4274
4275               rFalseIfx.condition ^= 1;
4276               genSkipc(&rFalseIfx);
4277             }
4278
4279             emitpLabel(truelbl->key);
4280
4281             if(ifx) ifx->generated = 1;
4282             return;
4283           }
4284
4285
4286           lit++;
4287           DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4288           i = (lit >> (size*8)) & 0xff;
4289
4290           emitpcode(POC_MOVLW, popGetLit(i));
4291           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4292
4293           while(size--) {
4294             i = (lit >> (size*8)) & 0xff;
4295
4296             if(i) {
4297               emitpcode(POC_MOVLW, popGetLit(i));
4298               emitSKPNZ;
4299               emitpcode(POC_SUBFW, popGet(AOP(right),size));
4300             } else {
4301               /* this byte of the lit is zero, 
4302                *if it's not the last then OR in the variable */
4303               if(size)
4304                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4305             }
4306           }
4307
4308
4309           emitpLabel(lbl->key);
4310
4311           rFalseIfx.condition ^= 1;
4312           genSkipc(&rFalseIfx);
4313         }
4314
4315         if(sign)
4316           emitpLabel(truelbl->key);
4317         if(ifx) ifx->generated = 1;
4318         return;
4319       }
4320     }
4321     /* Compare two variables */
4322
4323     DEBUGpic14_emitcode(";sign","%d",sign);
4324
4325     size--;
4326     if(sign) {
4327       /* Sigh. thus sucks... */
4328       if(size) {
4329         emitpcode(POC_MOVFW, popGet(AOP(left),size));
4330         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4331         emitpcode(POC_MOVLW, popGetLit(0x80));
4332         emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4333         emitpcode(POC_XORFW, popGet(AOP(right),size));
4334         emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4335       } else {
4336         /* Signed char comparison */
4337         /* Special thanks to Nikolai Golovchenko for this snippet */
4338         emitpcode(POC_MOVFW, popGet(AOP(right),0));
4339         emitpcode(POC_SUBFW, popGet(AOP(left),0));
4340         emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4341         emitpcode(POC_XORFW, popGet(AOP(left),0));
4342         emitpcode(POC_XORFW, popGet(AOP(right),0));
4343         emitpcode(POC_ADDLW, popGetLit(0x80));
4344
4345         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4346         genSkipc(&rFalseIfx);
4347           
4348         if(ifx) ifx->generated = 1;
4349         return;
4350       }
4351
4352     } else {
4353
4354       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4355       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4356     }
4357
4358
4359     /* The rest of the bytes of a multi-byte compare */
4360     while (size) {
4361
4362       emitSKPZ;
4363       emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4364       size--;
4365
4366       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4367       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4368
4369
4370     }
4371
4372     emitpLabel(lbl->key);
4373
4374     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4375     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4376         (AOP_TYPE(result) == AOP_REG)) {
4377       emitpcode(POC_CLRF, popGet(AOP(result),0));
4378       emitpcode(POC_RLF, popGet(AOP(result),0));
4379     } else {
4380       genSkipc(&rFalseIfx);
4381     }         
4382     //genSkipc(&rFalseIfx);
4383     if(ifx) ifx->generated = 1;
4384
4385     return;
4386
4387   }
4388
4389   // check_carry:
4390   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4391     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4392     pic14_outBitC(result);
4393   } else {
4394     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4395     /* if the result is used in the next
4396        ifx conditional branch then generate
4397        code a little differently */
4398     if (ifx )
4399       genIfxJump (ifx,"c");
4400     else
4401       pic14_outBitC(result);
4402     /* leave the result in acc */
4403   }
4404
4405 }
4406
4407 /*-----------------------------------------------------------------*/
4408 /* genCmpGt :- greater than comparison                             */
4409 /*-----------------------------------------------------------------*/
4410 static void genCmpGt (iCode *ic, iCode *ifx)
4411 {
4412     operand *left, *right, *result;
4413     sym_link *letype , *retype;
4414     int sign ;
4415
4416     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4417     left = IC_LEFT(ic);
4418     right= IC_RIGHT(ic);
4419     result = IC_RESULT(ic);
4420
4421     letype = getSpec(operandType(left));
4422     retype =getSpec(operandType(right));
4423     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4424     /* assign the amsops */
4425     aopOp (left,ic,FALSE);
4426     aopOp (right,ic,FALSE);
4427     aopOp (result,ic,TRUE);
4428
4429     genCmp(right, left, result, ifx, sign);
4430
4431     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4432     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4433     freeAsmop(result,NULL,ic,TRUE); 
4434 }
4435
4436 /*-----------------------------------------------------------------*/
4437 /* genCmpLt - less than comparisons                                */
4438 /*-----------------------------------------------------------------*/
4439 static void genCmpLt (iCode *ic, iCode *ifx)
4440 {
4441     operand *left, *right, *result;
4442     sym_link *letype , *retype;
4443     int sign ;
4444
4445     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4446     left = IC_LEFT(ic);
4447     right= IC_RIGHT(ic);
4448     result = IC_RESULT(ic);
4449
4450     letype = getSpec(operandType(left));
4451     retype =getSpec(operandType(right));
4452     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4453
4454     /* assign the amsops */
4455     aopOp (left,ic,FALSE);
4456     aopOp (right,ic,FALSE);
4457     aopOp (result,ic,TRUE);
4458
4459     genCmp(left, right, result, ifx, sign);
4460
4461     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4462     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4463     freeAsmop(result,NULL,ic,TRUE); 
4464 }
4465
4466 /*-----------------------------------------------------------------*/
4467 /* genc16bit2lit - compare a 16 bit value to a literal             */
4468 /*-----------------------------------------------------------------*/
4469 static void genc16bit2lit(operand *op, int lit, int offset)
4470 {
4471   int i;
4472
4473   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4474   if( (lit&0xff) == 0) 
4475     i=1;
4476   else
4477     i=0;
4478
4479   switch( BYTEofLONG(lit,i)) { 
4480   case 0:
4481     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4482     break;
4483   case 1:
4484     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4485     break;
4486   case 0xff:
4487     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4488     break;
4489   default:
4490     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4491     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4492   }
4493
4494   i ^= 1;
4495
4496   switch( BYTEofLONG(lit,i)) { 
4497   case 0:
4498     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4499     break;
4500   case 1:
4501     emitSKPNZ;
4502     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4503     break;
4504   case 0xff:
4505     emitSKPNZ;
4506     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4507     break;
4508   default:
4509     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4510     emitSKPNZ;
4511     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4512
4513   }
4514
4515 }
4516
4517 /*-----------------------------------------------------------------*/
4518 /* gencjneshort - compare and jump if not equal                    */
4519 /*-----------------------------------------------------------------*/
4520 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4521 {
4522   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4523   int offset = 0;
4524   int res_offset = 0;  /* the result may be a different size then left or right */
4525   int res_size = AOP_SIZE(result);
4526   resolvedIfx rIfx;
4527   symbol *lbl;
4528
4529   unsigned long lit = 0L;
4530   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4531   DEBUGpic14_AopType(__LINE__,left,right,result);
4532   if(result)
4533     DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4534   resolveIfx(&rIfx,ifx);
4535   lbl =  newiTempLabel(NULL);
4536
4537
4538   /* if the left side is a literal or 
4539      if the right is in a pointer register and left 
4540      is not */
4541   if ((AOP_TYPE(left) == AOP_LIT) || 
4542       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4543     operand *t = right;
4544     right = left;
4545     left = t;
4546   }
4547   if(AOP_TYPE(right) == AOP_LIT)
4548     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4549
4550   /* if the right side is a literal then anything goes */
4551   if (AOP_TYPE(right) == AOP_LIT &&
4552       AOP_TYPE(left) != AOP_DIR ) {
4553     switch(size) {
4554     case 2:
4555       genc16bit2lit(left, lit, 0);
4556       emitSKPNZ;
4557       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4558       break;
4559     default:
4560       while (size--) {
4561         if(lit & 0xff) {
4562           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4563           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4564         } else {
4565           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4566         }
4567
4568         emitSKPNZ;
4569         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4570         offset++;
4571         if(res_offset < res_size-1)
4572           res_offset++;
4573         lit >>= 8;
4574       }
4575       break;
4576     }
4577   }
4578
4579   /* if the right side is in a register or in direct space or
4580      if the left is a pointer register & right is not */    
4581   else if (AOP_TYPE(right) == AOP_REG ||
4582            AOP_TYPE(right) == AOP_DIR || 
4583            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4584            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4585     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4586     int lbl_key = lbl->key;
4587
4588     if(result) {
4589       emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4590       //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4591     }else {
4592       DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4593       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4594               __FUNCTION__,__LINE__);
4595       return;
4596     }
4597
4598 /*     switch(size) { */
4599 /*     case 2: */
4600 /*       genc16bit2lit(left, lit, 0); */
4601 /*       emitSKPNZ; */
4602 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4603 /*       break; */
4604 /*     default: */
4605     while (size--) {
4606       int emit_skip=1;
4607       if((AOP_TYPE(left) == AOP_DIR) && 
4608          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4609
4610         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4611         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4612
4613       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4614             
4615         switch (lit & 0xff) {
4616         case 0:
4617           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4618           break;
4619         case 1:
4620           emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4621           emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4622           //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4623           emit_skip=0;
4624           break;
4625         case 0xff:
4626           emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4627           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4628           //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4629           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4630           emit_skip=0;
4631           break;
4632         default:
4633           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4634           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4635         }
4636         lit >>= 8;
4637
4638       } else {
4639         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4640       }
4641       if(emit_skip) {
4642         if(AOP_TYPE(result) == AOP_CRY) {
4643           pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4644           if(rIfx.condition)
4645             emitSKPNZ;
4646           else
4647             emitSKPZ;
4648           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4649         } else {
4650           /* fix me. probably need to check result size too */
4651           //emitpcode(POC_CLRF,popGet(AOP(result),0));
4652           if(rIfx.condition)
4653             emitSKPZ;
4654           else
4655             emitSKPNZ;
4656           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4657           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4658         }
4659         if(ifx)
4660           ifx->generated=1;
4661       }
4662       emit_skip++;
4663       offset++;
4664       if(res_offset < res_size-1)
4665         res_offset++;
4666     }
4667 /*       break; */
4668 /*     } */
4669   } else if(AOP_TYPE(right) == AOP_REG &&
4670             AOP_TYPE(left) != AOP_DIR){
4671
4672     while(size--) {
4673       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4674       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4675       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4676       if(rIfx.condition)
4677         emitSKPNZ;
4678       else
4679         emitSKPZ;
4680       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4681       offset++;
4682       if(res_offset < res_size-1)
4683         res_offset++;
4684     }
4685       
4686   }else{
4687     /* right is a pointer reg need both a & b */
4688     while(size--) {
4689       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4690       if(strcmp(l,"b"))
4691         pic14_emitcode("mov","b,%s",l);
4692       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4693       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4694       offset++;
4695     }
4696   }
4697
4698   emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4699   if(!rIfx.condition)
4700     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4701
4702   emitpLabel(lbl->key);
4703
4704   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4705
4706   if(ifx)
4707     ifx->generated = 1;
4708 }
4709
4710 #if 0
4711 /*-----------------------------------------------------------------*/
4712 /* gencjne - compare and jump if not equal                         */
4713 /*-----------------------------------------------------------------*/
4714 static void gencjne(operand *left, operand *right, iCode *ifx)
4715 {
4716     symbol *tlbl  = newiTempLabel(NULL);
4717
4718     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4719     gencjneshort(left, right, lbl);
4720
4721     pic14_emitcode("mov","a,%s",one);
4722     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4723     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4724     pic14_emitcode("clr","a");
4725     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4726
4727     emitpLabel(lbl->key);
4728     emitpLabel(tlbl->key);
4729
4730 }
4731 #endif
4732
4733 /*-----------------------------------------------------------------*/
4734 /* genCmpEq - generates code for equal to                          */
4735 /*-----------------------------------------------------------------*/
4736 static void genCmpEq (iCode *ic, iCode *ifx)
4737 {
4738     operand *left, *right, *result;
4739     unsigned long lit = 0L;
4740     int size,offset=0;
4741
4742     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4743
4744     if(ifx)
4745       DEBUGpic14_emitcode ("; ifx is non-null","");
4746     else
4747       DEBUGpic14_emitcode ("; ifx is null","");
4748
4749     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4750     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4751     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4752
4753     size = max(AOP_SIZE(left),AOP_SIZE(right));
4754
4755     DEBUGpic14_AopType(__LINE__,left,right,result);
4756
4757     /* if literal, literal on the right or 
4758     if the right is in a pointer register and left 
4759     is not */
4760     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4761         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4762       operand *tmp = right ;
4763       right = left;
4764       left = tmp;
4765     }
4766
4767
4768     if(ifx && !AOP_SIZE(result)){
4769         symbol *tlbl;
4770         /* if they are both bit variables */
4771         if (AOP_TYPE(left) == AOP_CRY &&
4772             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4773             if(AOP_TYPE(right) == AOP_LIT){
4774                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4775                 if(lit == 0L){
4776                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4777                     pic14_emitcode("cpl","c");
4778                 } else if(lit == 1L) {
4779                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4780                 } else {
4781                     pic14_emitcode("clr","c");
4782                 }
4783                 /* AOP_TYPE(right) == AOP_CRY */
4784             } else {
4785                 symbol *lbl = newiTempLabel(NULL);
4786                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4787                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4788                 pic14_emitcode("cpl","c");
4789                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4790             }
4791             /* if true label then we jump if condition
4792             supplied is true */
4793             tlbl = newiTempLabel(NULL);
4794             if ( IC_TRUE(ifx) ) {
4795                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4796                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4797             } else {
4798                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4799                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4800             }
4801             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4802
4803             {
4804               /* left and right are both bit variables, result is carry */
4805               resolvedIfx rIfx;
4806               
4807               resolveIfx(&rIfx,ifx);
4808
4809               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4810               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4811               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4812               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4813               genSkipz2(&rIfx,0);
4814             }
4815         } else {
4816
4817           /* They're not both bit variables. Is the right a literal? */
4818           if(AOP_TYPE(right) == AOP_LIT) {
4819             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4820             
4821             switch(size) {
4822
4823             case 1:
4824               switch(lit & 0xff) {
4825               case 1:
4826                 if ( IC_TRUE(ifx) ) {
4827                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4828                   emitSKPNZ;
4829                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4830                 } else {
4831                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4832                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4833                 }
4834                 break;
4835               case 0xff:
4836                 if ( IC_TRUE(ifx) ) {
4837                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4838                   emitSKPNZ;
4839                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4840                 } else {
4841                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4842                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4843                 }
4844                 break;
4845               default:
4846                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4847                 if(lit)
4848                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4849                 genSkip(ifx,'z');
4850               }
4851
4852
4853               /* end of size == 1 */
4854               break;
4855               
4856             case 2:
4857               genc16bit2lit(left,lit,offset);
4858               genSkip(ifx,'z');
4859               break;
4860               /* end of size == 2 */
4861
4862             default:
4863               /* size is 4 */
4864               if(lit==0) {
4865                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4866                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4867                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4868                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4869
4870               } else {
4871
4872                 /* search for patterns that can be optimized */
4873
4874                 genc16bit2lit(left,lit,0);
4875                 lit >>= 16;
4876                 if(lit) {
4877                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4878                   //genSkip(ifx,'z');
4879                   genc16bit2lit(left,lit,2);
4880                 } else {
4881                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4882                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4883
4884                 }
4885                 
4886               }
4887
4888               genSkip(ifx,'z');
4889             }
4890           
4891             ifx->generated = 1;
4892             goto release ;
4893             
4894
4895           } else if(AOP_TYPE(right) == AOP_CRY ) {
4896             /* we know the left is not a bit, but that the right is */
4897             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4898             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4899                       popGet(AOP(right),offset));
4900             emitpcode(POC_XORLW,popGetLit(1));
4901
4902             /* if the two are equal, then W will be 0 and the Z bit is set
4903              * we could test Z now, or go ahead and check the high order bytes if
4904              * the variable we're comparing is larger than a byte. */
4905
4906             while(--size)
4907               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4908
4909             if ( IC_TRUE(ifx) ) {
4910               emitSKPNZ;
4911               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4912               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4913             } else {
4914               emitSKPZ;
4915               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4916               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4917             }
4918
4919           } else {
4920             /* They're both variables that are larger than bits */
4921             int s = size;
4922
4923             tlbl = newiTempLabel(NULL);
4924
4925             while(size--) {
4926               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4927               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4928
4929               if ( IC_TRUE(ifx) ) {
4930                 if(size) {
4931                   emitSKPZ;
4932                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4933                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4934                 } else {
4935                   emitSKPNZ;
4936                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4937                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4938                 }
4939               } else {
4940                 emitSKPZ;
4941                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4942                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4943               }
4944               offset++;
4945             }
4946             if(s>1 && IC_TRUE(ifx)) {
4947               emitpLabel(tlbl->key);
4948               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4949             }
4950           }
4951         }
4952         /* mark the icode as generated */
4953         ifx->generated = 1;
4954         goto release ;
4955     }
4956
4957     /* if they are both bit variables */
4958     if (AOP_TYPE(left) == AOP_CRY &&
4959         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4960         if(AOP_TYPE(right) == AOP_LIT){
4961             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4962             if(lit == 0L){
4963                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4964                 pic14_emitcode("cpl","c");
4965             } else if(lit == 1L) {
4966                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4967             } else {
4968                 pic14_emitcode("clr","c");
4969             }
4970             /* AOP_TYPE(right) == AOP_CRY */
4971         } else {
4972             symbol *lbl = newiTempLabel(NULL);
4973             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4974             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4975             pic14_emitcode("cpl","c");
4976             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4977         }
4978         /* c = 1 if egal */
4979         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4980             pic14_outBitC(result);
4981             goto release ;
4982         }
4983         if (ifx) {
4984             genIfxJump (ifx,"c");
4985             goto release ;
4986         }
4987         /* if the result is used in an arithmetic operation
4988         then put the result in place */
4989         pic14_outBitC(result);
4990     } else {
4991       
4992       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4993       gencjne(left,right,result,ifx);
4994 /*
4995       if(ifx) 
4996         gencjne(left,right,newiTempLabel(NULL));
4997       else {
4998         if(IC_TRUE(ifx)->key)
4999           gencjne(left,right,IC_TRUE(ifx)->key);
5000         else
5001           gencjne(left,right,IC_FALSE(ifx)->key);
5002         ifx->generated = 1;
5003         goto release ;
5004       }
5005       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5006         aopPut(AOP(result),"a",0);
5007         goto release ;
5008       }
5009
5010       if (ifx) {
5011         genIfxJump (ifx,"a");
5012         goto release ;
5013       }
5014 */
5015       /* if the result is used in an arithmetic operation
5016          then put the result in place */
5017 /*
5018       if (AOP_TYPE(result) != AOP_CRY) 
5019         pic14_outAcc(result);
5020 */
5021       /* leave the result in acc */
5022     }
5023
5024 release:
5025     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5026     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5027     freeAsmop(result,NULL,ic,TRUE);
5028 }
5029
5030 /*-----------------------------------------------------------------*/
5031 /* ifxForOp - returns the icode containing the ifx for operand     */
5032 /*-----------------------------------------------------------------*/
5033 static iCode *ifxForOp ( operand *op, iCode *ic )
5034 {
5035     /* if true symbol then needs to be assigned */
5036     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5037     if (IS_TRUE_SYMOP(op))
5038         return NULL ;
5039
5040     /* if this has register type condition and
5041     the next instruction is ifx with the same operand
5042     and live to of the operand is upto the ifx only then */
5043     if (ic->next &&
5044         ic->next->op == IFX &&
5045         IC_COND(ic->next)->key == op->key &&
5046         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5047         return ic->next;
5048
5049     if (ic->next &&
5050         ic->next->op == IFX &&
5051         IC_COND(ic->next)->key == op->key) {
5052       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5053       return ic->next;
5054     }
5055
5056     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5057     if (ic->next &&
5058         ic->next->op == IFX)
5059       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5060
5061     if (ic->next &&
5062         ic->next->op == IFX &&
5063         IC_COND(ic->next)->key == op->key) {
5064       DEBUGpic14_emitcode ("; "," key is okay");
5065       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5066                            OP_SYMBOL(op)->liveTo,
5067                            ic->next->seq);
5068     }
5069
5070
5071     return NULL;
5072 }
5073 /*-----------------------------------------------------------------*/
5074 /* genAndOp - for && operation                                     */
5075 /*-----------------------------------------------------------------*/
5076 static void genAndOp (iCode *ic)
5077 {
5078     operand *left,*right, *result;
5079 /*     symbol *tlbl; */
5080
5081     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5082     /* note here that && operations that are in an
5083     if statement are taken away by backPatchLabels
5084     only those used in arthmetic operations remain */
5085     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5086     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5087     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5088
5089     DEBUGpic14_AopType(__LINE__,left,right,result);
5090
5091     emitpcode(POC_MOVFW,popGet(AOP(left),0));
5092     emitpcode(POC_ANDFW,popGet(AOP(right),0));
5093     emitpcode(POC_MOVWF,popGet(AOP(result),0));
5094
5095     /* if both are bit variables */
5096 /*     if (AOP_TYPE(left) == AOP_CRY && */
5097 /*         AOP_TYPE(right) == AOP_CRY ) { */
5098 /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5099 /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5100 /*         pic14_outBitC(result); */
5101 /*     } else { */
5102 /*         tlbl = newiTempLabel(NULL); */
5103 /*         pic14_toBoolean(left);     */
5104 /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5105 /*         pic14_toBoolean(right); */
5106 /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5107 /*         pic14_outBitAcc(result); */
5108 /*     } */
5109
5110     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5111     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5112     freeAsmop(result,NULL,ic,TRUE);
5113 }
5114
5115
5116 /*-----------------------------------------------------------------*/
5117 /* genOrOp - for || operation                                      */
5118 /*-----------------------------------------------------------------*/
5119 /*
5120   tsd pic port -
5121   modified this code, but it doesn't appear to ever get called
5122 */
5123
5124 static void genOrOp (iCode *ic)
5125 {
5126     operand *left,*right, *result;
5127     symbol *tlbl;
5128
5129     /* note here that || operations that are in an
5130     if statement are taken away by backPatchLabels
5131     only those used in arthmetic operations remain */
5132     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5133     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5134     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5135     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5136
5137     DEBUGpic14_AopType(__LINE__,left,right,result);
5138
5139     /* if both are bit variables */
5140     if (AOP_TYPE(left) == AOP_CRY &&
5141         AOP_TYPE(right) == AOP_CRY ) {
5142       pic14_emitcode("clrc","");
5143       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5144                AOP(left)->aopu.aop_dir,
5145                AOP(left)->aopu.aop_dir);
5146       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5147                AOP(right)->aopu.aop_dir,
5148                AOP(right)->aopu.aop_dir);
5149       pic14_emitcode("setc","");
5150
5151     } else {
5152         tlbl = newiTempLabel(NULL);
5153         pic14_toBoolean(left);
5154         emitSKPZ;
5155         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5156         pic14_toBoolean(right);
5157         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5158
5159         pic14_outBitAcc(result);
5160     }
5161
5162     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5163     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5164     freeAsmop(result,NULL,ic,TRUE);            
5165 }
5166
5167 /*-----------------------------------------------------------------*/
5168 /* isLiteralBit - test if lit == 2^n                               */
5169 /*-----------------------------------------------------------------*/
5170 static int isLiteralBit(unsigned long lit)
5171 {
5172     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5173     0x100L,0x200L,0x400L,0x800L,
5174     0x1000L,0x2000L,0x4000L,0x8000L,
5175     0x10000L,0x20000L,0x40000L,0x80000L,
5176     0x100000L,0x200000L,0x400000L,0x800000L,
5177     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5178     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5179     int idx;
5180     
5181     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5182     for(idx = 0; idx < 32; idx++)
5183         if(lit == pw[idx])
5184             return idx+1;
5185     return 0;
5186 }
5187
5188 /*-----------------------------------------------------------------*/
5189 /* continueIfTrue -                                                */
5190 /*-----------------------------------------------------------------*/
5191 static void continueIfTrue (iCode *ic)
5192 {
5193     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5194     if(IC_TRUE(ic))
5195         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5196     ic->generated = 1;
5197 }
5198
5199 /*-----------------------------------------------------------------*/
5200 /* jmpIfTrue -                                                     */
5201 /*-----------------------------------------------------------------*/
5202 static void jumpIfTrue (iCode *ic)
5203 {
5204     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5205     if(!IC_TRUE(ic))
5206         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5207     ic->generated = 1;
5208 }
5209
5210 /*-----------------------------------------------------------------*/
5211 /* jmpTrueOrFalse -                                                */
5212 /*-----------------------------------------------------------------*/
5213 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5214 {
5215     // ugly but optimized by peephole
5216     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5217     if(IC_TRUE(ic)){
5218         symbol *nlbl = newiTempLabel(NULL);
5219         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5220         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5221         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5222         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5223     }
5224     else{
5225         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5226         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5227     }
5228     ic->generated = 1;
5229 }
5230
5231 /*-----------------------------------------------------------------*/
5232 /* genAnd  - code for and                                          */
5233 /*-----------------------------------------------------------------*/
5234 static void genAnd (iCode *ic, iCode *ifx)
5235 {
5236   operand *left, *right, *result;
5237   int size, offset=0;  
5238   unsigned long lit = 0L;
5239   int bytelit = 0;
5240   resolvedIfx rIfx;
5241
5242
5243   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5244   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5245   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5246   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5247
5248   resolveIfx(&rIfx,ifx);
5249
5250   /* if left is a literal & right is not then exchange them */
5251   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5252       AOP_NEEDSACC(left)) {
5253     operand *tmp = right ;
5254     right = left;
5255     left = tmp;
5256   }
5257
5258   /* if result = right then exchange them */
5259   if(pic14_sameRegs(AOP(result),AOP(right))){
5260     operand *tmp = right ;
5261     right = left;
5262     left = tmp;
5263   }
5264
5265   /* if right is bit then exchange them */
5266   if (AOP_TYPE(right) == AOP_CRY &&
5267       AOP_TYPE(left) != AOP_CRY){
5268     operand *tmp = right ;
5269     right = left;
5270     left = tmp;
5271   }
5272   if(AOP_TYPE(right) == AOP_LIT)
5273     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5274
5275   size = AOP_SIZE(result);
5276
5277   DEBUGpic14_AopType(__LINE__,left,right,result);
5278
5279   // if(bit & yy)
5280   // result = bit & yy;
5281   if (AOP_TYPE(left) == AOP_CRY){
5282     // c = bit & literal;
5283     if(AOP_TYPE(right) == AOP_LIT){
5284       if(lit & 1) {
5285         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5286           // no change
5287           goto release;
5288         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5289       } else {
5290         // bit(result) = 0;
5291         if(size && (AOP_TYPE(result) == AOP_CRY)){
5292           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5293           goto release;
5294         }
5295         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5296           jumpIfTrue(ifx);
5297           goto release;
5298         }
5299         pic14_emitcode("clr","c");
5300       }
5301     } else {
5302       if (AOP_TYPE(right) == AOP_CRY){
5303         // c = bit & bit;
5304         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5305         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5306       } else {
5307         // c = bit & val;
5308         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5309         // c = lsb
5310         pic14_emitcode("rrc","a");
5311         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5312       }
5313     }
5314     // bit = c
5315     // val = c
5316     if(size)
5317       pic14_outBitC(result);
5318     // if(bit & ...)
5319     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5320       genIfxJump(ifx, "c");           
5321     goto release ;
5322   }
5323
5324   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5325   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5326   if((AOP_TYPE(right) == AOP_LIT) &&
5327      (AOP_TYPE(result) == AOP_CRY) &&
5328      (AOP_TYPE(left) != AOP_CRY)){
5329     int posbit = isLiteralBit(lit);
5330     /* left &  2^n */
5331     if(posbit){
5332       posbit--;
5333       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5334       // bit = left & 2^n
5335       if(size)
5336         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5337       // if(left &  2^n)
5338       else{
5339         if(ifx){
5340 /*
5341           if(IC_TRUE(ifx)) {
5342             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5343             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
5344           } else {
5345             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5346             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
5347           }
5348 */
5349           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5350                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5351           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5352           
5353           ifx->generated = 1;
5354         }
5355         goto release;
5356       }
5357     } else {
5358       symbol *tlbl = newiTempLabel(NULL);
5359       int sizel = AOP_SIZE(left);
5360       if(size)
5361         pic14_emitcode("setb","c");
5362       while(sizel--){
5363         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5364           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5365           // byte ==  2^n ?
5366           if((posbit = isLiteralBit(bytelit)) != 0)
5367             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5368           else{
5369             if(bytelit != 0x0FFL)
5370               pic14_emitcode("anl","a,%s",
5371                              aopGet(AOP(right),offset,FALSE,TRUE));
5372             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5373           }
5374         }
5375         offset++;
5376       }
5377       // bit = left & literal
5378       if(size){
5379         pic14_emitcode("clr","c");
5380         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5381       }
5382       // if(left & literal)
5383       else{
5384         if(ifx)
5385           jmpTrueOrFalse(ifx, tlbl);
5386         goto release ;
5387       }
5388     }
5389     pic14_outBitC(result);
5390     goto release ;
5391   }
5392
5393   /* if left is same as result */
5394   if(pic14_sameRegs(AOP(result),AOP(left))){
5395     int know_W = -1;
5396     for(;size--; offset++,lit>>=8) {
5397       if(AOP_TYPE(right) == AOP_LIT){
5398         switch(lit & 0xff) {
5399         case 0x00:
5400           /*  and'ing with 0 has clears the result */
5401           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5402           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5403           break;
5404         case 0xff:
5405           /* and'ing with 0xff is a nop when the result and left are the same */
5406           break;
5407
5408         default:
5409           {
5410             int p = my_powof2( (~lit) & 0xff );
5411             if(p>=0) {
5412               /* only one bit is set in the literal, so use a bcf instruction */
5413               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5414               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5415
5416             } else {
5417               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5418               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5419               if(know_W != (lit&0xff))
5420                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5421               know_W = lit &0xff;
5422               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5423             }
5424           }    
5425         }
5426       } else {
5427         if (AOP_TYPE(left) == AOP_ACC) {
5428           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5429         } else {                    
5430           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5431           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5432
5433         }
5434       }
5435     }
5436
5437   } else {
5438     // left & result in different registers
5439     if(AOP_TYPE(result) == AOP_CRY){
5440       // result = bit
5441       // if(size), result in bit
5442       // if(!size && ifx), conditional oper: if(left & right)
5443       symbol *tlbl = newiTempLabel(NULL);
5444       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5445       if(size)
5446         pic14_emitcode("setb","c");
5447       while(sizer--){
5448         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5449         pic14_emitcode("anl","a,%s",
5450                        aopGet(AOP(left),offset,FALSE,FALSE));
5451         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5452         offset++;
5453       }
5454       if(size){
5455         CLRC;
5456         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5457         pic14_outBitC(result);
5458       } else if(ifx)
5459         jmpTrueOrFalse(ifx, tlbl);
5460     } else {
5461       for(;(size--);offset++) {
5462         // normal case
5463         // result = left & right
5464         if(AOP_TYPE(right) == AOP_LIT){
5465           int t = (lit >> (offset*8)) & 0x0FFL;
5466           switch(t) { 
5467           case 0x00:
5468             pic14_emitcode("clrf","%s",
5469                            aopGet(AOP(result),offset,FALSE,FALSE));
5470             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5471             break;
5472           case 0xff:
5473             if(AOP_TYPE(left) != AOP_ACC) {
5474               pic14_emitcode("movf","%s,w",
5475                              aopGet(AOP(left),offset,FALSE,FALSE));
5476               pic14_emitcode("movwf","%s",
5477                              aopGet(AOP(result),offset,FALSE,FALSE));
5478               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5479             }
5480             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5481             break;
5482           default:
5483             if(AOP_TYPE(left) == AOP_ACC) {
5484               emitpcode(POC_ANDLW, popGetLit(t));
5485             } else {
5486               pic14_emitcode("movlw","0x%x",t);
5487               pic14_emitcode("andwf","%s,w",
5488                              aopGet(AOP(left),offset,FALSE,FALSE));
5489               pic14_emitcode("movwf","%s",
5490                              aopGet(AOP(result),offset,FALSE,FALSE));
5491               
5492               emitpcode(POC_MOVLW, popGetLit(t));
5493               emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5494             }
5495             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5496           }
5497           continue;
5498         }
5499
5500         if (AOP_TYPE(left) == AOP_ACC) {
5501           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5502           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5503         } else {
5504           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5505           pic14_emitcode("andwf","%s,w",
5506                          aopGet(AOP(left),offset,FALSE,FALSE));
5507           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5508           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5509         }
5510         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5511         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5512       }
5513     }
5514   }
5515
5516   release :
5517     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5518   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5519   freeAsmop(result,NULL,ic,TRUE);     
5520 }
5521
5522 /*-----------------------------------------------------------------*/
5523 /* genOr  - code for or                                            */
5524 /*-----------------------------------------------------------------*/
5525 static void genOr (iCode *ic, iCode *ifx)
5526 {
5527     operand *left, *right, *result;
5528     int size, offset=0;
5529     unsigned long lit = 0L;
5530
5531     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5532
5533     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5534     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5535     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5536
5537     DEBUGpic14_AopType(__LINE__,left,right,result);
5538
5539     /* if left is a literal & right is not then exchange them */
5540     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5541         AOP_NEEDSACC(left)) {
5542         operand *tmp = right ;
5543         right = left;
5544         left = tmp;
5545     }
5546
5547     /* if result = right then exchange them */
5548     if(pic14_sameRegs(AOP(result),AOP(right))){
5549         operand *tmp = right ;
5550         right = left;
5551         left = tmp;
5552     }
5553
5554     /* if right is bit then exchange them */
5555     if (AOP_TYPE(right) == AOP_CRY &&
5556         AOP_TYPE(left) != AOP_CRY){
5557         operand *tmp = right ;
5558         right = left;
5559         left = tmp;
5560     }
5561
5562     DEBUGpic14_AopType(__LINE__,left,right,result);
5563
5564     if(AOP_TYPE(right) == AOP_LIT)
5565         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5566
5567     size = AOP_SIZE(result);
5568
5569     // if(bit | yy)
5570     // xx = bit | yy;
5571     if (AOP_TYPE(left) == AOP_CRY){
5572         if(AOP_TYPE(right) == AOP_LIT){
5573             // c = bit & literal;
5574             if(lit){
5575                 // lit != 0 => result = 1
5576                 if(AOP_TYPE(result) == AOP_CRY){
5577                   if(size)
5578                     emitpcode(POC_BSF, popGet(AOP(result),0));
5579                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5580                   //     AOP(result)->aopu.aop_dir,
5581                   //     AOP(result)->aopu.aop_dir);
5582                     else if(ifx)
5583                         continueIfTrue(ifx);
5584                     goto release;
5585                 }
5586             } else {
5587                 // lit == 0 => result = left
5588                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5589                     goto release;
5590                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5591             }
5592         } else {
5593             if (AOP_TYPE(right) == AOP_CRY){
5594               if(pic14_sameRegs(AOP(result),AOP(left))){
5595                 // c = bit | bit;
5596                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5597                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5598                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5599
5600                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5601                          AOP(result)->aopu.aop_dir,
5602                          AOP(result)->aopu.aop_dir);
5603                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5604                          AOP(right)->aopu.aop_dir,
5605                          AOP(right)->aopu.aop_dir);
5606                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5607                          AOP(result)->aopu.aop_dir,
5608                          AOP(result)->aopu.aop_dir);
5609               } else {
5610                 if( AOP_TYPE(result) == AOP_ACC) {
5611                   emitpcode(POC_MOVLW, popGetLit(0));
5612                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5613                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5614                   emitpcode(POC_MOVLW, popGetLit(1));
5615
5616                 } else {
5617
5618                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5619                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5620                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5621                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5622
5623                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5624                                  AOP(result)->aopu.aop_dir,
5625                                  AOP(result)->aopu.aop_dir);
5626                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5627                                  AOP(right)->aopu.aop_dir,
5628                                  AOP(right)->aopu.aop_dir);
5629                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5630                                  AOP(left)->aopu.aop_dir,
5631                                  AOP(left)->aopu.aop_dir);
5632                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5633                                  AOP(result)->aopu.aop_dir,
5634                                  AOP(result)->aopu.aop_dir);
5635                 }
5636               }
5637             } else {
5638                 // c = bit | val;
5639                 symbol *tlbl = newiTempLabel(NULL);
5640                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5641
5642
5643                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5644                 if( AOP_TYPE(right) == AOP_ACC) {
5645                   emitpcode(POC_IORLW, popGetLit(0));
5646                   emitSKPNZ;
5647                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5648                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5649                 }
5650
5651
5652
5653                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5654                     pic14_emitcode(";XXX setb","c");
5655                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5656                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5657                 pic14_toBoolean(right);
5658                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5659                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5660                     jmpTrueOrFalse(ifx, tlbl);
5661                     goto release;
5662                 } else {
5663                     CLRC;
5664                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5665                 }
5666             }
5667         }
5668         // bit = c
5669         // val = c
5670         if(size)
5671             pic14_outBitC(result);
5672         // if(bit | ...)
5673         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5674             genIfxJump(ifx, "c");           
5675         goto release ;
5676     }
5677
5678     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5679     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5680     if((AOP_TYPE(right) == AOP_LIT) &&
5681        (AOP_TYPE(result) == AOP_CRY) &&
5682        (AOP_TYPE(left) != AOP_CRY)){
5683         if(lit){
5684           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5685             // result = 1
5686             if(size)
5687                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5688             else 
5689                 continueIfTrue(ifx);
5690             goto release;
5691         } else {
5692           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5693             // lit = 0, result = boolean(left)
5694             if(size)
5695                 pic14_emitcode(";XXX setb","c");
5696             pic14_toBoolean(right);
5697             if(size){
5698                 symbol *tlbl = newiTempLabel(NULL);
5699                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5700                 CLRC;
5701                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5702             } else {
5703                 genIfxJump (ifx,"a");
5704                 goto release;
5705             }
5706         }
5707         pic14_outBitC(result);
5708         goto release ;
5709     }
5710
5711     /* if left is same as result */
5712     if(pic14_sameRegs(AOP(result),AOP(left))){
5713       int know_W = -1;
5714       for(;size--; offset++,lit>>=8) {
5715         if(AOP_TYPE(right) == AOP_LIT){
5716           if((lit & 0xff) == 0)
5717             /*  or'ing with 0 has no effect */
5718             continue;
5719           else {
5720             int p = my_powof2(lit & 0xff);
5721             if(p>=0) {
5722               /* only one bit is set in the literal, so use a bsf instruction */
5723               emitpcode(POC_BSF,
5724                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5725             } else {
5726               if(know_W != (lit & 0xff))
5727                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5728               know_W = lit & 0xff;
5729               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5730             }
5731                     
5732           }
5733         } else {
5734           if (AOP_TYPE(left) == AOP_ACC) {
5735             emitpcode(POC_IORFW,  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_IORWF,  popGet(AOP(left),offset));
5740
5741             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5742             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5743
5744           }
5745         }
5746       }
5747     } else {
5748         // left & result in different registers
5749         if(AOP_TYPE(result) == AOP_CRY){
5750             // result = bit
5751             // if(size), result in bit
5752             // if(!size && ifx), conditional oper: if(left | right)
5753             symbol *tlbl = newiTempLabel(NULL);
5754             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5755             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5756
5757
5758             if(size)
5759                 pic14_emitcode(";XXX setb","c");
5760             while(sizer--){
5761                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5762                 pic14_emitcode(";XXX orl","a,%s",
5763                          aopGet(AOP(left),offset,FALSE,FALSE));
5764                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5765                 offset++;
5766             }
5767             if(size){
5768                 CLRC;
5769                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5770                 pic14_outBitC(result);
5771             } else if(ifx)
5772                 jmpTrueOrFalse(ifx, tlbl);
5773         } else for(;(size--);offset++){
5774           // normal case
5775           // result = left & right
5776           if(AOP_TYPE(right) == AOP_LIT){
5777             int t = (lit >> (offset*8)) & 0x0FFL;
5778             switch(t) { 
5779             case 0x00:
5780               if (AOP_TYPE(left) != AOP_ACC) {
5781                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5782               }
5783               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5784
5785               break;
5786             default:
5787               if (AOP_TYPE(left) == AOP_ACC) {
5788                 emitpcode(POC_IORLW,  popGetLit(t));
5789               } else {
5790                 emitpcode(POC_MOVLW,  popGetLit(t));
5791                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5792               }
5793               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));              
5794             }
5795             continue;
5796           }
5797
5798           // faster than result <- left, anl result,right
5799           // and better if result is SFR
5800           if (AOP_TYPE(left) == AOP_ACC) {
5801             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5802             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5803           } else {
5804             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5805             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5806
5807             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5808             pic14_emitcode("iorwf","%s,w",
5809                      aopGet(AOP(left),offset,FALSE,FALSE));
5810           }
5811           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5812           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5813         }
5814     }
5815
5816 release :
5817     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5818     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5819     freeAsmop(result,NULL,ic,TRUE);     
5820 }
5821
5822 /*-----------------------------------------------------------------*/
5823 /* genXor - code for xclusive or                                   */
5824 /*-----------------------------------------------------------------*/
5825 static void genXor (iCode *ic, iCode *ifx)
5826 {
5827   operand *left, *right, *result;
5828   int size, offset=0;
5829   unsigned long lit = 0L;
5830
5831   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5832
5833   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5834   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5835   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5836
5837   /* if left is a literal & right is not ||
5838      if left needs acc & right does not */
5839   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5840       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5841     operand *tmp = right ;
5842     right = left;
5843     left = tmp;
5844   }
5845
5846   /* if result = right then exchange them */
5847   if(pic14_sameRegs(AOP(result),AOP(right))){
5848     operand *tmp = right ;
5849     right = left;
5850     left = tmp;
5851   }
5852
5853   /* if right is bit then exchange them */
5854   if (AOP_TYPE(right) == AOP_CRY &&
5855       AOP_TYPE(left) != AOP_CRY){
5856     operand *tmp = right ;
5857     right = left;
5858     left = tmp;
5859   }
5860   if(AOP_TYPE(right) == AOP_LIT)
5861     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5862
5863   size = AOP_SIZE(result);
5864
5865   // if(bit ^ yy)
5866   // xx = bit ^ yy;
5867   if (AOP_TYPE(left) == AOP_CRY){
5868     if(AOP_TYPE(right) == AOP_LIT){
5869       // c = bit & literal;
5870       if(lit>>1){
5871         // lit>>1  != 0 => result = 1
5872         if(AOP_TYPE(result) == AOP_CRY){
5873           if(size)
5874             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5875             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5876           else if(ifx)
5877             continueIfTrue(ifx);
5878           goto release;
5879         }
5880         pic14_emitcode("setb","c");
5881       } else{
5882         // lit == (0 or 1)
5883         if(lit == 0){
5884           // lit == 0, result = left
5885           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5886             goto release;
5887           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5888         } else{
5889           // lit == 1, result = not(left)
5890           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5891             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5892             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5893             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5894             goto release;
5895           } else {
5896             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5897             pic14_emitcode("cpl","c");
5898           }
5899         }
5900       }
5901
5902     } else {
5903       // right != literal
5904       symbol *tlbl = newiTempLabel(NULL);
5905       if (AOP_TYPE(right) == AOP_CRY){
5906         // c = bit ^ bit;
5907         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5908       }
5909       else{
5910         int sizer = AOP_SIZE(right);
5911         // c = bit ^ val
5912         // if val>>1 != 0, result = 1
5913         pic14_emitcode("setb","c");
5914         while(sizer){
5915           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5916           if(sizer == 1)
5917             // test the msb of the lsb
5918             pic14_emitcode("anl","a,#0xfe");
5919           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5920           sizer--;
5921         }
5922         // val = (0,1)
5923         pic14_emitcode("rrc","a");
5924       }
5925       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5926       pic14_emitcode("cpl","c");
5927       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5928     }
5929     // bit = c
5930     // val = c
5931     if(size)
5932       pic14_outBitC(result);
5933     // if(bit | ...)
5934     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5935       genIfxJump(ifx, "c");           
5936     goto release ;
5937   }
5938
5939   if(pic14_sameRegs(AOP(result),AOP(left))){
5940     /* if left is same as result */
5941     for(;size--; offset++) {
5942       if(AOP_TYPE(right) == AOP_LIT){
5943         int t  = (lit >> (offset*8)) & 0x0FFL;
5944         if(t == 0x00L)
5945           continue;
5946         else
5947           if (IS_AOP_PREG(left)) {
5948             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5949             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5950             aopPut(AOP(result),"a",offset);
5951           } else {
5952             emitpcode(POC_MOVLW, popGetLit(t));
5953             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5954             pic14_emitcode("xrl","%s,%s",
5955                            aopGet(AOP(left),offset,FALSE,TRUE),
5956                            aopGet(AOP(right),offset,FALSE,FALSE));
5957           }
5958       } else {
5959         if (AOP_TYPE(left) == AOP_ACC)
5960           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5961         else {
5962           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5963           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5964 /*
5965           if (IS_AOP_PREG(left)) {
5966             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5967             aopPut(AOP(result),"a",offset);
5968           } else
5969             pic14_emitcode("xrl","%s,a",
5970                            aopGet(AOP(left),offset,FALSE,TRUE));
5971 */
5972         }
5973       }
5974     }
5975   } else {
5976     // left & result in different registers
5977     if(AOP_TYPE(result) == AOP_CRY){
5978       // result = bit
5979       // if(size), result in bit
5980       // if(!size && ifx), conditional oper: if(left ^ right)
5981       symbol *tlbl = newiTempLabel(NULL);
5982       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5983       if(size)
5984         pic14_emitcode("setb","c");
5985       while(sizer--){
5986         if((AOP_TYPE(right) == AOP_LIT) &&
5987            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5988           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5989         } else {
5990           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5991           pic14_emitcode("xrl","a,%s",
5992                          aopGet(AOP(left),offset,FALSE,FALSE));
5993         }
5994         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5995         offset++;
5996       }
5997       if(size){
5998         CLRC;
5999         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6000         pic14_outBitC(result);
6001       } else if(ifx)
6002         jmpTrueOrFalse(ifx, tlbl);
6003     } else for(;(size--);offset++){
6004       // normal case
6005       // result = left & right
6006       if(AOP_TYPE(right) == AOP_LIT){
6007         int t = (lit >> (offset*8)) & 0x0FFL;
6008         switch(t) { 
6009         case 0x00:
6010           if (AOP_TYPE(left) != AOP_ACC) {
6011             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6012           }
6013           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6014           pic14_emitcode("movf","%s,w",
6015                          aopGet(AOP(left),offset,FALSE,FALSE));
6016           pic14_emitcode("movwf","%s",
6017                          aopGet(AOP(result),offset,FALSE,FALSE));
6018           break;
6019         case 0xff:
6020           if (AOP_TYPE(left) == AOP_ACC) {
6021             emitpcode(POC_XORLW, popGetLit(t));
6022           } else {
6023             emitpcode(POC_COMFW,popGet(AOP(left),offset));
6024           }
6025           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6026           break;
6027         default:
6028           if (AOP_TYPE(left) == AOP_ACC) {
6029             emitpcode(POC_XORLW, popGetLit(t));
6030           } else {
6031             emitpcode(POC_MOVLW, popGetLit(t));
6032             emitpcode(POC_XORFW,popGet(AOP(left),offset));
6033           }
6034           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6035           pic14_emitcode("movlw","0x%x",t);
6036           pic14_emitcode("xorwf","%s,w",
6037                          aopGet(AOP(left),offset,FALSE,FALSE));
6038           pic14_emitcode("movwf","%s",
6039                          aopGet(AOP(result),offset,FALSE,FALSE));
6040
6041         }
6042         continue;
6043       }
6044
6045       // faster than result <- left, anl result,right
6046       // and better if result is SFR
6047       if (AOP_TYPE(left) == AOP_ACC) {
6048         emitpcode(POC_XORFW,popGet(AOP(right),offset));
6049         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6050       } else {
6051         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6052         emitpcode(POC_XORFW,popGet(AOP(left),offset));
6053         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6054         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
6055       }
6056       if ( AOP_TYPE(result) != AOP_ACC){
6057         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6058         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
6059       }
6060     }
6061   }
6062
6063   release :
6064     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6065   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6066   freeAsmop(result,NULL,ic,TRUE);     
6067 }
6068
6069 /*-----------------------------------------------------------------*/
6070 /* genInline - write the inline code out                           */
6071 /*-----------------------------------------------------------------*/
6072 static void genInline (iCode *ic)
6073 {
6074     char *buffer, *bp, *bp1;
6075     
6076     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6077
6078     _G.inLine += (!options.asmpeep);
6079
6080     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6081     strcpy(buffer,IC_INLINE(ic));
6082
6083     /* emit each line as a code */
6084     while (*bp) {
6085         if (*bp == '\n') {
6086             *bp++ = '\0';
6087
6088             if(*bp1)
6089               addpCode2pBlock(pb,AssembleLine(bp1));
6090             bp1 = bp;
6091         } else {
6092             if (*bp == ':') {
6093                 bp++;
6094                 *bp = '\0';
6095                 bp++;
6096                 pic14_emitcode(bp1,"");
6097                 bp1 = bp;
6098             } else
6099                 bp++;
6100         }
6101     }
6102     if ((bp1 != bp) && *bp1)
6103       addpCode2pBlock(pb,AssembleLine(bp1));
6104
6105     Safe_free(buffer);
6106
6107     _G.inLine -= (!options.asmpeep);
6108 }
6109
6110 /*-----------------------------------------------------------------*/
6111 /* genRRC - rotate right with carry                                */
6112 /*-----------------------------------------------------------------*/
6113 static void genRRC (iCode *ic)
6114 {
6115   operand *left , *result ;
6116   int size, offset = 0, same;
6117
6118   /* rotate right with carry */
6119   left = IC_LEFT(ic);
6120   result=IC_RESULT(ic);
6121   aopOp (left,ic,FALSE);
6122   aopOp (result,ic,FALSE);
6123
6124   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6125
6126   same = pic14_sameRegs(AOP(result),AOP(left));
6127
6128   size = AOP_SIZE(result);    
6129
6130   /* get the lsb and put it into the carry */
6131   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6132
6133   offset = 0 ;
6134
6135   while(size--) {
6136
6137     if(same) {
6138       emitpcode(POC_RRF, popGet(AOP(left),offset));
6139     } else {
6140       emitpcode(POC_RRFW, popGet(AOP(left),offset));
6141       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6142     }
6143
6144     offset++;
6145   }
6146
6147   freeAsmop(left,NULL,ic,TRUE);
6148   freeAsmop(result,NULL,ic,TRUE);
6149 }
6150
6151 /*-----------------------------------------------------------------*/
6152 /* genRLC - generate code for rotate left with carry               */
6153 /*-----------------------------------------------------------------*/
6154 static void genRLC (iCode *ic)
6155 {    
6156   operand *left , *result ;
6157   int size, offset = 0;
6158   int same;
6159
6160   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6161   /* rotate right with carry */
6162   left = IC_LEFT(ic);
6163   result=IC_RESULT(ic);
6164   aopOp (left,ic,FALSE);
6165   aopOp (result,ic,FALSE);
6166
6167   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6168
6169   same = pic14_sameRegs(AOP(result),AOP(left));
6170
6171   /* move it to the result */
6172   size = AOP_SIZE(result);    
6173
6174   /* get the msb and put it into the carry */
6175   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6176
6177   offset = 0 ;
6178
6179   while(size--) {
6180
6181     if(same) {
6182       emitpcode(POC_RLF, popGet(AOP(left),offset));
6183     } else {
6184       emitpcode(POC_RLFW, popGet(AOP(left),offset));
6185       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6186     }
6187
6188     offset++;
6189   }
6190
6191
6192   freeAsmop(left,NULL,ic,TRUE);
6193   freeAsmop(result,NULL,ic,TRUE);
6194 }
6195
6196 /*-----------------------------------------------------------------*/
6197 /* genGetHbit - generates code get highest order bit               */
6198 /*-----------------------------------------------------------------*/
6199 static void genGetHbit (iCode *ic)
6200 {
6201     operand *left, *result;
6202     left = IC_LEFT(ic);
6203     result=IC_RESULT(ic);
6204     aopOp (left,ic,FALSE);
6205     aopOp (result,ic,FALSE);
6206
6207     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6208     /* get the highest order byte into a */
6209     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6210     if(AOP_TYPE(result) == AOP_CRY){
6211         pic14_emitcode("rlc","a");
6212         pic14_outBitC(result);
6213     }
6214     else{
6215         pic14_emitcode("rl","a");
6216         pic14_emitcode("anl","a,#0x01");
6217         pic14_outAcc(result);
6218     }
6219
6220
6221     freeAsmop(left,NULL,ic,TRUE);
6222     freeAsmop(result,NULL,ic,TRUE);
6223 }
6224
6225 /*-----------------------------------------------------------------*/
6226 /* AccRol - rotate left accumulator by known count                 */
6227 /*-----------------------------------------------------------------*/
6228 static void AccRol (int shCount)
6229 {
6230     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6231     shCount &= 0x0007;              // shCount : 0..7
6232     switch(shCount){
6233         case 0 :
6234             break;
6235         case 1 :
6236             pic14_emitcode("rl","a");
6237             break;
6238         case 2 :
6239             pic14_emitcode("rl","a");
6240             pic14_emitcode("rl","a");
6241             break;
6242         case 3 :
6243             pic14_emitcode("swap","a");
6244             pic14_emitcode("rr","a");
6245             break;
6246         case 4 :
6247             pic14_emitcode("swap","a");
6248             break;
6249         case 5 :
6250             pic14_emitcode("swap","a");
6251             pic14_emitcode("rl","a");
6252             break;
6253         case 6 :
6254             pic14_emitcode("rr","a");
6255             pic14_emitcode("rr","a");
6256             break;
6257         case 7 :
6258             pic14_emitcode("rr","a");
6259             break;
6260     }
6261 }
6262
6263 /*-----------------------------------------------------------------*/
6264 /* AccLsh - left shift accumulator by known count                  */
6265 /*-----------------------------------------------------------------*/
6266 static void AccLsh (int shCount)
6267 {
6268     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6269     if(shCount != 0){
6270         if(shCount == 1)
6271             pic14_emitcode("add","a,acc");
6272         else 
6273             if(shCount == 2) {
6274             pic14_emitcode("add","a,acc");
6275             pic14_emitcode("add","a,acc");
6276         } else {
6277             /* rotate left accumulator */
6278             AccRol(shCount);
6279             /* and kill the lower order bits */
6280             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6281         }
6282     }
6283 }
6284
6285 /*-----------------------------------------------------------------*/
6286 /* AccRsh - right shift accumulator by known count                 */
6287 /*-----------------------------------------------------------------*/
6288 static void AccRsh (int shCount)
6289 {
6290     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6291     if(shCount != 0){
6292         if(shCount == 1){
6293             CLRC;
6294             pic14_emitcode("rrc","a");
6295         } else {
6296             /* rotate right accumulator */
6297             AccRol(8 - shCount);
6298             /* and kill the higher order bits */
6299             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6300         }
6301     }
6302 }
6303
6304 #if 0
6305 /*-----------------------------------------------------------------*/
6306 /* AccSRsh - signed right shift accumulator by known count                 */
6307 /*-----------------------------------------------------------------*/
6308 static void AccSRsh (int shCount)
6309 {
6310     symbol *tlbl ;
6311     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6312     if(shCount != 0){
6313         if(shCount == 1){
6314             pic14_emitcode("mov","c,acc.7");
6315             pic14_emitcode("rrc","a");
6316         } else if(shCount == 2){
6317             pic14_emitcode("mov","c,acc.7");
6318             pic14_emitcode("rrc","a");
6319             pic14_emitcode("mov","c,acc.7");
6320             pic14_emitcode("rrc","a");
6321         } else {
6322             tlbl = newiTempLabel(NULL);
6323             /* rotate right accumulator */
6324             AccRol(8 - shCount);
6325             /* and kill the higher order bits */
6326             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6327             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6328             pic14_emitcode("orl","a,#0x%02x",
6329                      (unsigned char)~SRMask[shCount]);
6330             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6331         }
6332     }
6333 }
6334 #endif
6335 /*-----------------------------------------------------------------*/
6336 /* shiftR1Left2Result - shift right one byte from left to result   */
6337 /*-----------------------------------------------------------------*/
6338 static void shiftR1Left2ResultSigned (operand *left, int offl,
6339                                 operand *result, int offr,
6340                                 int shCount)
6341 {
6342   int same;
6343
6344   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6345
6346   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6347
6348   switch(shCount) {
6349   case 1:
6350     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6351     if(same) 
6352       emitpcode(POC_RRF, popGet(AOP(result),offr));
6353     else {
6354       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6355       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6356     }
6357
6358     break;
6359   case 2:
6360
6361     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6362     if(same) 
6363       emitpcode(POC_RRF, popGet(AOP(result),offr));
6364     else {
6365       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6366       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6367     }
6368     emitpcode(POC_RLFW, popGet(AOP(result),offr));
6369     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6370
6371     break;
6372
6373   case 3:
6374     if(same)
6375       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6376     else {
6377       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6378       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6379     }
6380
6381     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6382     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6383     emitpcode(POC_ANDLW, popGetLit(0x1f));
6384
6385     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6386     emitpcode(POC_IORLW, popGetLit(0xe0));
6387
6388     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6389     break;
6390
6391   case 4:
6392     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6393     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6394     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6395     emitpcode(POC_IORLW,  popGetLit(0xf0));
6396     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6397     break;
6398   case 5:
6399     if(same) {
6400       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6401     } else {
6402       emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6403       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6404     }
6405     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6406     emitpcode(POC_ANDLW,  popGetLit(0x07));
6407     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6408     emitpcode(POC_IORLW,  popGetLit(0xf8));
6409     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6410     break;
6411
6412   case 6:
6413     if(same) {
6414       emitpcode(POC_MOVLW, popGetLit(0x00));
6415       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6416       emitpcode(POC_MOVLW, popGetLit(0xfe));
6417       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6418       emitpcode(POC_IORLW, popGetLit(0x01));
6419       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6420     } else {
6421       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6422       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6423       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6424       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6425       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6426     }
6427     break;
6428
6429   case 7:
6430     if(same) {
6431       emitpcode(POC_MOVLW, popGetLit(0x00));
6432       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6433       emitpcode(POC_MOVLW, popGetLit(0xff));
6434       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6435     } else {
6436       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6437       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6438       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6439     }
6440
6441   default:
6442     break;
6443   }
6444 }
6445
6446 /*-----------------------------------------------------------------*/
6447 /* shiftR1Left2Result - shift right one byte from left to result   */
6448 /*-----------------------------------------------------------------*/
6449 static void shiftR1Left2Result (operand *left, int offl,
6450                                 operand *result, int offr,
6451                                 int shCount, int sign)
6452 {
6453   int same;
6454
6455   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6456
6457   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6458
6459   /* Copy the msb into the carry if signed. */
6460   if(sign) {
6461     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6462     return;
6463   }
6464
6465
6466
6467   switch(shCount) {
6468   case 1:
6469     emitCLRC;
6470     if(same) 
6471       emitpcode(POC_RRF, popGet(AOP(result),offr));
6472     else {
6473       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6474       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6475     }
6476     break;
6477   case 2:
6478     emitCLRC;
6479     if(same) {
6480       emitpcode(POC_RRF, popGet(AOP(result),offr));
6481     } else {
6482       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6483       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6484     }
6485     emitCLRC;
6486     emitpcode(POC_RRF, popGet(AOP(result),offr));
6487
6488     break;
6489   case 3:
6490     if(same)
6491       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6492     else {
6493       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6494       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6495     }
6496
6497     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6498     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6499     emitpcode(POC_ANDLW, popGetLit(0x1f));
6500     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6501     break;
6502       
6503   case 4:
6504     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6505     emitpcode(POC_ANDLW, popGetLit(0x0f));
6506     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6507     break;
6508
6509   case 5:
6510     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6511     emitpcode(POC_ANDLW, popGetLit(0x0f));
6512     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6513     emitCLRC;
6514     emitpcode(POC_RRF, popGet(AOP(result),offr));
6515
6516     break;
6517   case 6:
6518
6519     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6520     emitpcode(POC_ANDLW, popGetLit(0x80));
6521     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6522     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6523     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6524     break;
6525
6526   case 7:
6527
6528     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6529     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6530     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6531
6532     break;
6533
6534   default:
6535     break;
6536   }
6537 }
6538
6539 /*-----------------------------------------------------------------*/
6540 /* shiftL1Left2Result - shift left one byte from left to result    */
6541 /*-----------------------------------------------------------------*/
6542 static void shiftL1Left2Result (operand *left, int offl,
6543                                 operand *result, int offr, int shCount)
6544 {
6545   int same;
6546
6547   //    char *l;
6548   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6549
6550   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6551   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6552     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6553     //    MOVA(l);
6554     /* shift left accumulator */
6555     //AccLsh(shCount); // don't comment out just yet...
6556   //    aopPut(AOP(result),"a",offr);
6557
6558   switch(shCount) {
6559   case 1:
6560     /* Shift left 1 bit position */
6561     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6562     if(same) {
6563       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6564     } else {
6565       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6566       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6567     }
6568     break;
6569   case 2:
6570     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6571     emitpcode(POC_ANDLW,popGetLit(0x7e));
6572     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6573     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6574     break;
6575   case 3:
6576     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6577     emitpcode(POC_ANDLW,popGetLit(0x3e));
6578     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6579     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6580     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6581     break;
6582   case 4:
6583     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6584     emitpcode(POC_ANDLW, popGetLit(0xf0));
6585     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6586     break;
6587   case 5:
6588     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6589     emitpcode(POC_ANDLW, popGetLit(0xf0));
6590     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6591     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6592     break;
6593   case 6:
6594     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6595     emitpcode(POC_ANDLW, popGetLit(0x30));
6596     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6597     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6598     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6599     break;
6600   case 7:
6601     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6602     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6603     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6604     break;
6605
6606   default:
6607     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6608   }
6609
6610 }
6611
6612 /*-----------------------------------------------------------------*/
6613 /* movLeft2Result - move byte from left to result                  */
6614 /*-----------------------------------------------------------------*/
6615 static void movLeft2Result (operand *left, int offl,
6616                             operand *result, int offr)
6617 {
6618   char *l;
6619   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6620   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6621     l = aopGet(AOP(left),offl,FALSE,FALSE);
6622
6623     if (*l == '@' && (IS_AOP_PREG(result))) {
6624       pic14_emitcode("mov","a,%s",l);
6625       aopPut(AOP(result),"a",offr);
6626     } else {
6627       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6628       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6629     }
6630   }
6631 }
6632
6633 /*-----------------------------------------------------------------*/
6634 /* shiftL2Left2Result - shift left two bytes from left to result   */
6635 /*-----------------------------------------------------------------*/
6636 static void shiftL2Left2Result (operand *left, int offl,
6637                                 operand *result, int offr, int shCount)
6638 {
6639
6640
6641   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6642
6643   if(pic14_sameRegs(AOP(result), AOP(left))) {
6644     switch(shCount) {
6645     case 0:
6646       break;
6647     case 1:
6648     case 2:
6649     case 3:
6650
6651       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6652       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6653       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6654
6655       while(--shCount) {
6656         emitCLRC;
6657         emitpcode(POC_RLF, popGet(AOP(result),offr));
6658         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6659       }
6660
6661       break;
6662     case 4:
6663     case 5:
6664       emitpcode(POC_MOVLW, popGetLit(0x0f));
6665       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6666       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6667       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6668       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6669       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6670       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6671       if(shCount >=5) {
6672         emitpcode(POC_RLF, popGet(AOP(result),offr));
6673         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6674       }
6675       break;
6676     case 6:
6677       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6678       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6679       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6680       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6681       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6682       emitpcode(POC_ANDLW,popGetLit(0xc0));
6683       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6684       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6685       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6686       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6687       break;
6688     case 7:
6689       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6690       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6691       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6692       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6693       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6694     }
6695
6696   } else {
6697     switch(shCount) {
6698     case 0:
6699       break;
6700     case 1:
6701     case 2:
6702     case 3:
6703       /* note, use a mov/add for the shift since the mov has a
6704          chance of getting optimized out */
6705       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6706       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6707       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6708       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6709       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6710
6711       while(--shCount) {
6712         emitCLRC;
6713         emitpcode(POC_RLF, popGet(AOP(result),offr));
6714         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6715       }
6716       break;
6717
6718     case 4:
6719     case 5:
6720       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6721       emitpcode(POC_ANDLW, popGetLit(0xF0));
6722       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6723       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6724       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6725       emitpcode(POC_ANDLW, popGetLit(0xF0));
6726       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6727       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6728
6729
6730       if(shCount == 5) {
6731         emitpcode(POC_RLF, popGet(AOP(result),offr));
6732         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6733       }
6734       break;
6735     case 6:
6736       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6737       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6738       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6739       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6740
6741       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6742       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6743       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6744       emitpcode(POC_ANDLW,popGetLit(0xc0));
6745       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6746       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6747       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6748       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6749       break;
6750     case 7:
6751       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6752       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6753       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6754       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6755       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6756     }
6757   }
6758
6759 }
6760 /*-----------------------------------------------------------------*/
6761 /* shiftR2Left2Result - shift right two bytes from left to result  */
6762 /*-----------------------------------------------------------------*/
6763 static void shiftR2Left2Result (operand *left, int offl,
6764                                 operand *result, int offr,
6765                                 int shCount, int sign)
6766 {
6767   int same=0;
6768
6769   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6770   same = pic14_sameRegs(AOP(result), AOP(left));
6771
6772   if(same && ((offl + MSB16) == offr)){
6773     same=1;
6774     /* don't crash result[offr] */
6775     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6776     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6777   }
6778 /* else {
6779     movLeft2Result(left,offl, result, offr);
6780     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6781   }
6782 */
6783   /* a:x >> shCount (x = lsb(result))*/
6784 /*
6785   if(sign)
6786     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6787   else {
6788     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6789 */
6790   switch(shCount) {
6791   case 0:
6792     break;
6793   case 1:
6794   case 2:
6795   case 3:
6796     if(sign)
6797       emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6798     else
6799       emitCLRC;
6800
6801     if(same) {
6802       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6803       emitpcode(POC_RRF,popGet(AOP(result),offr));
6804     } else {
6805       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6806       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6807       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6808       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6809     }
6810
6811     while(--shCount) {
6812       if(sign)
6813         emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6814       else
6815         emitCLRC;
6816       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6817       emitpcode(POC_RRF,popGet(AOP(result),offr));
6818     }
6819     break;
6820   case 4:
6821   case 5:
6822     if(same) {
6823
6824       emitpcode(POC_MOVLW, popGetLit(0xf0));
6825       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6826       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6827
6828       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6829       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6830       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6831       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6832     } else {
6833       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6834       emitpcode(POC_ANDLW, popGetLit(0x0f));
6835       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6836
6837       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6838       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6839       emitpcode(POC_ANDLW, popGetLit(0xf0));
6840       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6841       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6842     }
6843
6844     if(shCount >=5) {
6845       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6846       emitpcode(POC_RRF, popGet(AOP(result),offr));
6847     }
6848
6849     if(sign) {
6850       emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6851       emitpcode(POC_BTFSC, 
6852                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6853       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6854     }
6855
6856     break;
6857
6858   case 6:
6859     if(same) {
6860
6861       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6862       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6863
6864       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6865       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6866       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6867       emitpcode(POC_ANDLW,popGetLit(0x03));
6868       if(sign) {
6869         emitpcode(POC_BTFSC, 
6870                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6871         emitpcode(POC_IORLW,popGetLit(0xfc));
6872       }
6873       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6874       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6875       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6876       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6877     } else {
6878       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6879       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6880       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6881       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6882       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6883       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6884       emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6885       emitpcode(POC_ANDLW,popGetLit(0x03));
6886       if(sign) {
6887         emitpcode(POC_BTFSC, 
6888                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6889         emitpcode(POC_IORLW,popGetLit(0xfc));
6890       }
6891       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6892       //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6893
6894         
6895     }
6896
6897     break;
6898   case 7:
6899     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6900     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6901     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6902     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6903     if(sign) {
6904       emitSKPNC;
6905       emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6906     } else 
6907       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6908   }
6909 }
6910
6911
6912 /*-----------------------------------------------------------------*/
6913 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6914 /*-----------------------------------------------------------------*/
6915 static void shiftLLeftOrResult (operand *left, int offl,
6916                                 operand *result, int offr, int shCount)
6917 {
6918     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6919     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6920     /* shift left accumulator */
6921     AccLsh(shCount);
6922     /* or with result */
6923     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6924     /* back to result */
6925     aopPut(AOP(result),"a",offr);
6926 }
6927
6928 /*-----------------------------------------------------------------*/
6929 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6930 /*-----------------------------------------------------------------*/
6931 static void shiftRLeftOrResult (operand *left, int offl,
6932                                 operand *result, int offr, int shCount)
6933 {
6934     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6935     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6936     /* shift right accumulator */
6937     AccRsh(shCount);
6938     /* or with result */
6939     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6940     /* back to result */
6941     aopPut(AOP(result),"a",offr);
6942 }
6943
6944 /*-----------------------------------------------------------------*/
6945 /* genlshOne - left shift a one byte quantity by known count       */
6946 /*-----------------------------------------------------------------*/
6947 static void genlshOne (operand *result, operand *left, int shCount)
6948 {       
6949     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6950     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6951 }
6952
6953 /*-----------------------------------------------------------------*/
6954 /* genlshTwo - left shift two bytes by known amount != 0           */
6955 /*-----------------------------------------------------------------*/
6956 static void genlshTwo (operand *result,operand *left, int shCount)
6957 {
6958     int size;
6959     
6960     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6961     size = pic14_getDataSize(result);
6962
6963     /* if shCount >= 8 */
6964     if (shCount >= 8) {
6965         shCount -= 8 ;
6966
6967         if (size > 1){
6968             if (shCount)
6969                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6970             else 
6971                 movLeft2Result(left, LSB, result, MSB16);
6972         }
6973         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6974     }
6975
6976     /*  1 <= shCount <= 7 */
6977     else {  
6978         if(size == 1)
6979             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6980         else 
6981             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6982     }
6983 }
6984
6985 /*-----------------------------------------------------------------*/
6986 /* shiftLLong - shift left one long from left to result            */
6987 /* offl = LSB or MSB16                                             */
6988 /*-----------------------------------------------------------------*/
6989 static void shiftLLong (operand *left, operand *result, int offr )
6990 {
6991     char *l;
6992     int size = AOP_SIZE(result);
6993
6994     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6995     if(size >= LSB+offr){
6996         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6997         MOVA(l);
6998         pic14_emitcode("add","a,acc");
6999         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7000             size >= MSB16+offr && offr != LSB )
7001             pic14_emitcode("xch","a,%s",
7002                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7003         else        
7004             aopPut(AOP(result),"a",LSB+offr);
7005     }
7006
7007     if(size >= MSB16+offr){
7008         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7009             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7010             MOVA(l);
7011         }
7012         pic14_emitcode("rlc","a");
7013         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7014             size >= MSB24+offr && offr != LSB)
7015             pic14_emitcode("xch","a,%s",
7016                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7017         else        
7018             aopPut(AOP(result),"a",MSB16+offr);
7019     }
7020
7021     if(size >= MSB24+offr){
7022         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7023             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7024             MOVA(l);
7025         }
7026         pic14_emitcode("rlc","a");
7027         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7028             size >= MSB32+offr && offr != LSB )
7029             pic14_emitcode("xch","a,%s",
7030                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7031         else        
7032             aopPut(AOP(result),"a",MSB24+offr);
7033     }
7034
7035     if(size > MSB32+offr){
7036         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7037             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7038             MOVA(l);    
7039         }
7040         pic14_emitcode("rlc","a");
7041         aopPut(AOP(result),"a",MSB32+offr);
7042     }
7043     if(offr != LSB)
7044         aopPut(AOP(result),zero,LSB);       
7045 }
7046
7047 /*-----------------------------------------------------------------*/
7048 /* genlshFour - shift four byte by a known amount != 0             */
7049 /*-----------------------------------------------------------------*/
7050 static void genlshFour (operand *result, operand *left, int shCount)
7051 {
7052     int size;
7053
7054     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7055     size = AOP_SIZE(result);
7056
7057     /* if shifting more that 3 bytes */
7058     if (shCount >= 24 ) {
7059         shCount -= 24;
7060         if (shCount)
7061             /* lowest order of left goes to the highest
7062             order of the destination */
7063             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7064         else
7065             movLeft2Result(left, LSB, result, MSB32);
7066         aopPut(AOP(result),zero,LSB);
7067         aopPut(AOP(result),zero,MSB16);
7068         aopPut(AOP(result),zero,MSB32);
7069         return;
7070     }
7071
7072     /* more than two bytes */
7073     else if ( shCount >= 16 ) {
7074         /* lower order two bytes goes to higher order two bytes */
7075         shCount -= 16;
7076         /* if some more remaining */
7077         if (shCount)
7078             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7079         else {
7080             movLeft2Result(left, MSB16, result, MSB32);
7081             movLeft2Result(left, LSB, result, MSB24);
7082         }
7083         aopPut(AOP(result),zero,MSB16);
7084         aopPut(AOP(result),zero,LSB);
7085         return;
7086     }    
7087
7088     /* if more than 1 byte */
7089     else if ( shCount >= 8 ) {
7090         /* lower order three bytes goes to higher order  three bytes */
7091         shCount -= 8;
7092         if(size == 2){
7093             if(shCount)
7094                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7095             else
7096                 movLeft2Result(left, LSB, result, MSB16);
7097         }
7098         else{   /* size = 4 */
7099             if(shCount == 0){
7100                 movLeft2Result(left, MSB24, result, MSB32);
7101                 movLeft2Result(left, MSB16, result, MSB24);
7102                 movLeft2Result(left, LSB, result, MSB16);
7103                 aopPut(AOP(result),zero,LSB);
7104             }
7105             else if(shCount == 1)
7106                 shiftLLong(left, result, MSB16);
7107             else{
7108                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7109                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7110                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7111                 aopPut(AOP(result),zero,LSB);
7112             }
7113         }
7114     }
7115
7116     /* 1 <= shCount <= 7 */
7117     else if(shCount <= 2){
7118         shiftLLong(left, result, LSB);
7119         if(shCount == 2)
7120             shiftLLong(result, result, LSB);
7121     }
7122     /* 3 <= shCount <= 7, optimize */
7123     else{
7124         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7125         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7126         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7127     }
7128 }
7129
7130 /*-----------------------------------------------------------------*/
7131 /* genLeftShiftLiteral - left shifting by known count              */
7132 /*-----------------------------------------------------------------*/
7133 static void genLeftShiftLiteral (operand *left,
7134                                  operand *right,
7135                                  operand *result,
7136                                  iCode *ic)
7137 {    
7138     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7139     int size;
7140
7141     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7142     freeAsmop(right,NULL,ic,TRUE);
7143
7144     aopOp(left,ic,FALSE);
7145     aopOp(result,ic,FALSE);
7146
7147     size = getSize(operandType(result));
7148
7149 #if VIEW_SIZE
7150     pic14_emitcode("; shift left ","result %d, left %d",size,
7151              AOP_SIZE(left));
7152 #endif
7153
7154     /* I suppose that the left size >= result size */
7155     if(shCount == 0){
7156         while(size--){
7157             movLeft2Result(left, size, result, size);
7158         }
7159     }
7160
7161     else if(shCount >= (size * 8))
7162         while(size--)
7163             aopPut(AOP(result),zero,size);
7164     else{
7165         switch (size) {
7166             case 1:
7167                 genlshOne (result,left,shCount);
7168                 break;
7169
7170             case 2:
7171             case 3:
7172                 genlshTwo (result,left,shCount);
7173                 break;
7174
7175             case 4:
7176                 genlshFour (result,left,shCount);
7177                 break;
7178         }
7179     }
7180     freeAsmop(left,NULL,ic,TRUE);
7181     freeAsmop(result,NULL,ic,TRUE);
7182 }
7183
7184 /*-----------------------------------------------------------------*
7185  * genMultiAsm - repeat assembly instruction for size of register.
7186  * if endian == 1, then the high byte (i.e base address + size of 
7187  * register) is used first else the low byte is used first;
7188  *-----------------------------------------------------------------*/
7189 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7190 {
7191
7192   int offset = 0;
7193
7194   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7195
7196   if(!reg)
7197     return;
7198
7199   if(!endian) {
7200     endian = 1;
7201   } else {
7202     endian = -1;
7203     offset = size-1;
7204   }
7205
7206   while(size--) {
7207     emitpcode(poc,    popGet(AOP(reg),offset));
7208     offset += endian;
7209   }
7210
7211 }
7212 /*-----------------------------------------------------------------*/
7213 /* genLeftShift - generates code for left shifting                 */
7214 /*-----------------------------------------------------------------*/
7215 static void genLeftShift (iCode *ic)
7216 {
7217   operand *left,*right, *result;
7218   int size, offset;
7219   char *l;
7220   symbol *tlbl , *tlbl1;
7221   pCodeOp *pctemp;
7222
7223   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7224
7225   right = IC_RIGHT(ic);
7226   left  = IC_LEFT(ic);
7227   result = IC_RESULT(ic);
7228
7229   aopOp(right,ic,FALSE);
7230
7231   /* if the shift count is known then do it 
7232      as efficiently as possible */
7233   if (AOP_TYPE(right) == AOP_LIT) {
7234     genLeftShiftLiteral (left,right,result,ic);
7235     return ;
7236   }
7237
7238   /* shift count is unknown then we have to form 
7239      a loop get the loop count in B : Note: we take
7240      only the lower order byte since shifting
7241      more that 32 bits make no sense anyway, ( the
7242      largest size of an object can be only 32 bits ) */  
7243
7244     
7245   aopOp(left,ic,FALSE);
7246   aopOp(result,ic,FALSE);
7247
7248   /* now move the left to the result if they are not the
7249      same */
7250   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7251       AOP_SIZE(result) > 1) {
7252
7253     size = AOP_SIZE(result);
7254     offset=0;
7255     while (size--) {
7256       l = aopGet(AOP(left),offset,FALSE,TRUE);
7257       if (*l == '@' && (IS_AOP_PREG(result))) {
7258
7259         pic14_emitcode("mov","a,%s",l);
7260         aopPut(AOP(result),"a",offset);
7261       } else {
7262         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7263         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7264         //aopPut(AOP(result),l,offset);
7265       }
7266       offset++;
7267     }
7268   }
7269
7270   size = AOP_SIZE(result);
7271
7272   /* if it is only one byte then */
7273   if (size == 1) {
7274     if(optimized_for_speed) {
7275       emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7276       emitpcode(POC_ANDLW,  popGetLit(0xf0));
7277       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7278       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7279       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7280       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7281       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7282       emitpcode(POC_RLFW,   popGet(AOP(result),0));
7283       emitpcode(POC_ANDLW,  popGetLit(0xfe));
7284       emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7285       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7286       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7287     } else {
7288
7289       tlbl = newiTempLabel(NULL);
7290       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7291         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7292         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7293       }
7294
7295       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7296       emitpcode(POC_RRF,    popGet(AOP(result),0));
7297       emitpLabel(tlbl->key);
7298       emitpcode(POC_RLF,    popGet(AOP(result),0));
7299       emitpcode(POC_ADDLW,  popGetLit(1));
7300       emitSKPC;
7301       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7302     }
7303     goto release ;
7304   }
7305     
7306   if (pic14_sameRegs(AOP(left),AOP(result))) {
7307
7308     tlbl = newiTempLabel(NULL);
7309     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7310     genMultiAsm(POC_RRF, result, size,1);
7311     emitpLabel(tlbl->key);
7312     genMultiAsm(POC_RLF, result, size,0);
7313     emitpcode(POC_ADDLW,  popGetLit(1));
7314     emitSKPC;
7315     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7316     goto release;
7317   }
7318
7319   //tlbl = newiTempLabel(NULL);
7320   //offset = 0 ;   
7321   //tlbl1 = newiTempLabel(NULL);
7322
7323   //reAdjustPreg(AOP(result));    
7324     
7325   //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7326   //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7327   //l = aopGet(AOP(result),offset,FALSE,FALSE);
7328   //MOVA(l);
7329   //pic14_emitcode("add","a,acc");         
7330   //aopPut(AOP(result),"a",offset++);
7331   //while (--size) {
7332   //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7333   //  MOVA(l);
7334   //  pic14_emitcode("rlc","a");         
7335   //  aopPut(AOP(result),"a",offset++);
7336   //}
7337   //reAdjustPreg(AOP(result));
7338
7339   //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7340   //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7341
7342
7343   tlbl = newiTempLabel(NULL);
7344   tlbl1= newiTempLabel(NULL);
7345
7346   size = AOP_SIZE(result);
7347   offset = 1;
7348
7349   pctemp = popGetTempReg();  /* grab a temporary working register. */
7350
7351   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7352
7353   /* offset should be 0, 1 or 3 */
7354   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7355   emitSKPNZ;
7356   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7357
7358   emitpcode(POC_MOVWF, pctemp);
7359
7360
7361   emitpLabel(tlbl->key);
7362
7363   emitCLRC;
7364   emitpcode(POC_RLF,  popGet(AOP(result),0));
7365   while(--size)
7366     emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7367
7368   emitpcode(POC_DECFSZ,  pctemp);
7369   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7370   emitpLabel(tlbl1->key);
7371
7372   popReleaseTempReg(pctemp);
7373
7374
7375  release:
7376   freeAsmop (right,NULL,ic,TRUE);
7377   freeAsmop(left,NULL,ic,TRUE);
7378   freeAsmop(result,NULL,ic,TRUE);
7379 }
7380
7381 /*-----------------------------------------------------------------*/
7382 /* genrshOne - right shift a one byte quantity by known count      */
7383 /*-----------------------------------------------------------------*/
7384 static void genrshOne (operand *result, operand *left,
7385                        int shCount, int sign)
7386 {
7387     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7388     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7389 }
7390
7391 /*-----------------------------------------------------------------*/
7392 /* genrshTwo - right shift two bytes by known amount != 0          */
7393 /*-----------------------------------------------------------------*/
7394 static void genrshTwo (operand *result,operand *left,
7395                        int shCount, int sign)
7396 {
7397   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7398   /* if shCount >= 8 */
7399   if (shCount >= 8) {
7400     shCount -= 8 ;
7401     if (shCount)
7402       shiftR1Left2Result(left, MSB16, result, LSB,
7403                          shCount, sign);
7404     else
7405       movLeft2Result(left, MSB16, result, LSB);
7406
7407     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7408
7409     if(sign) {
7410       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7411       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7412     }
7413   }
7414
7415   /*  1 <= shCount <= 7 */
7416   else
7417     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7418 }
7419
7420 /*-----------------------------------------------------------------*/
7421 /* shiftRLong - shift right one long from left to result           */
7422 /* offl = LSB or MSB16                                             */
7423 /*-----------------------------------------------------------------*/
7424 static void shiftRLong (operand *left, int offl,
7425                         operand *result, int sign)
7426 {
7427     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7428     if(!sign)
7429         pic14_emitcode("clr","c");
7430     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7431     if(sign)
7432         pic14_emitcode("mov","c,acc.7");
7433     pic14_emitcode("rrc","a");
7434     aopPut(AOP(result),"a",MSB32-offl);
7435     if(offl == MSB16)
7436         /* add sign of "a" */
7437         addSign(result, MSB32, sign);
7438
7439     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7440     pic14_emitcode("rrc","a");
7441     aopPut(AOP(result),"a",MSB24-offl);
7442
7443     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7444     pic14_emitcode("rrc","a");
7445     aopPut(AOP(result),"a",MSB16-offl);
7446
7447     if(offl == LSB){
7448         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7449         pic14_emitcode("rrc","a");
7450         aopPut(AOP(result),"a",LSB);
7451     }
7452 }
7453
7454 /*-----------------------------------------------------------------*/
7455 /* genrshFour - shift four byte by a known amount != 0             */
7456 /*-----------------------------------------------------------------*/
7457 static void genrshFour (operand *result, operand *left,
7458                         int shCount, int sign)
7459 {
7460   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7461   /* if shifting more that 3 bytes */
7462   if(shCount >= 24 ) {
7463     shCount -= 24;
7464     if(shCount)
7465       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7466     else
7467       movLeft2Result(left, MSB32, result, LSB);
7468
7469     addSign(result, MSB16, sign);
7470   }
7471   else if(shCount >= 16){
7472     shCount -= 16;
7473     if(shCount)
7474       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7475     else{
7476       movLeft2Result(left, MSB24, result, LSB);
7477       movLeft2Result(left, MSB32, result, MSB16);
7478     }
7479     addSign(result, MSB24, sign);
7480   }
7481   else if(shCount >= 8){
7482     shCount -= 8;
7483     if(shCount == 1)
7484       shiftRLong(left, MSB16, result, sign);
7485     else if(shCount == 0){
7486       movLeft2Result(left, MSB16, result, LSB);
7487       movLeft2Result(left, MSB24, result, MSB16);
7488       movLeft2Result(left, MSB32, result, MSB24);
7489       addSign(result, MSB32, sign);
7490     }
7491     else{
7492       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7493       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7494       /* the last shift is signed */
7495       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7496       addSign(result, MSB32, sign);
7497     }
7498   }
7499   else{   /* 1 <= shCount <= 7 */
7500     if(shCount <= 2){
7501       shiftRLong(left, LSB, result, sign);
7502       if(shCount == 2)
7503         shiftRLong(result, LSB, result, sign);
7504     }
7505     else{
7506       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7507       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7508       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7509     }
7510   }
7511 }
7512
7513 /*-----------------------------------------------------------------*/
7514 /* genRightShiftLiteral - right shifting by known count            */
7515 /*-----------------------------------------------------------------*/
7516 static void genRightShiftLiteral (operand *left,
7517                                   operand *right,
7518                                   operand *result,
7519                                   iCode *ic,
7520                                   int sign)
7521 {    
7522   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7523   int lsize,res_size;
7524
7525   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7526   freeAsmop(right,NULL,ic,TRUE);
7527
7528   aopOp(left,ic,FALSE);
7529   aopOp(result,ic,FALSE);
7530
7531 #if VIEW_SIZE
7532   pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7533                  AOP_SIZE(left));
7534 #endif
7535
7536   lsize = pic14_getDataSize(left);
7537   res_size = pic14_getDataSize(result);
7538   /* test the LEFT size !!! */
7539
7540   /* I suppose that the left size >= result size */
7541   if(shCount == 0){
7542     while(res_size--)
7543       movLeft2Result(left, lsize, result, res_size);
7544   }
7545
7546   else if(shCount >= (lsize * 8)){
7547
7548     if(res_size == 1) {
7549       emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7550       if(sign) {
7551         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7552         emitpcode(POC_DECF, popGet(AOP(result),LSB));
7553       }
7554     } else {
7555
7556       if(sign) {
7557         emitpcode(POC_MOVLW, popGetLit(0));
7558         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7559         emitpcode(POC_MOVLW, popGetLit(0xff));
7560         while(res_size--)
7561           emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7562
7563       } else {
7564
7565         while(res_size--)
7566           emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7567       }
7568     }
7569   } else {
7570
7571     switch (res_size) {
7572     case 1:
7573       genrshOne (result,left,shCount,sign);
7574       break;
7575
7576     case 2:
7577       genrshTwo (result,left,shCount,sign);
7578       break;
7579
7580     case 4:
7581       genrshFour (result,left,shCount,sign);
7582       break;
7583     default :
7584       break;
7585     }
7586
7587   }
7588
7589   freeAsmop(left,NULL,ic,TRUE);
7590   freeAsmop(result,NULL,ic,TRUE);
7591 }
7592
7593 /*-----------------------------------------------------------------*/
7594 /* genSignedRightShift - right shift of signed number              */
7595 /*-----------------------------------------------------------------*/
7596 static void genSignedRightShift (iCode *ic)
7597 {
7598   operand *right, *left, *result;
7599   int size, offset;
7600   //  char *l;
7601   symbol *tlbl, *tlbl1 ;
7602   pCodeOp *pctemp;
7603
7604   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7605
7606   /* we do it the hard way put the shift count in b
7607      and loop thru preserving the sign */
7608   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7609
7610   right = IC_RIGHT(ic);
7611   left  = IC_LEFT(ic);
7612   result = IC_RESULT(ic);
7613
7614   aopOp(right,ic,FALSE);  
7615   aopOp(left,ic,FALSE);
7616   aopOp(result,ic,FALSE);
7617
7618
7619   if ( AOP_TYPE(right) == AOP_LIT) {
7620     genRightShiftLiteral (left,right,result,ic,1);
7621     return ;
7622   }
7623   /* shift count is unknown then we have to form 
7624      a loop get the loop count in B : Note: we take
7625      only the lower order byte since shifting
7626      more that 32 bits make no sense anyway, ( the
7627      largest size of an object can be only 32 bits ) */  
7628
7629   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7630   //pic14_emitcode("inc","b");
7631   //freeAsmop (right,NULL,ic,TRUE);
7632   //aopOp(left,ic,FALSE);
7633   //aopOp(result,ic,FALSE);
7634
7635   /* now move the left to the result if they are not the
7636      same */
7637   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7638       AOP_SIZE(result) > 1) {
7639
7640     size = AOP_SIZE(result);
7641     offset=0;
7642     while (size--) { 
7643       /*
7644         l = aopGet(AOP(left),offset,FALSE,TRUE);
7645         if (*l == '@' && IS_AOP_PREG(result)) {
7646
7647         pic14_emitcode("mov","a,%s",l);
7648         aopPut(AOP(result),"a",offset);
7649         } else
7650         aopPut(AOP(result),l,offset);
7651       */
7652       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7653       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7654
7655       offset++;
7656     }
7657   }
7658
7659   /* mov the highest order bit to OVR */    
7660   tlbl = newiTempLabel(NULL);
7661   tlbl1= newiTempLabel(NULL);
7662
7663   size = AOP_SIZE(result);
7664   offset = size - 1;
7665
7666   pctemp = popGetTempReg();  /* grab a temporary working register. */
7667
7668   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7669
7670   /* offset should be 0, 1 or 3 */
7671   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7672   emitSKPNZ;
7673   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7674
7675   emitpcode(POC_MOVWF, pctemp);
7676
7677
7678   emitpLabel(tlbl->key);
7679
7680   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7681   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7682
7683   while(--size) {
7684     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7685   }
7686
7687   emitpcode(POC_DECFSZ,  pctemp);
7688   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7689   emitpLabel(tlbl1->key);
7690
7691   popReleaseTempReg(pctemp);
7692 #if 0
7693   size = AOP_SIZE(result);
7694   offset = size - 1;
7695   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7696   pic14_emitcode("rlc","a");
7697   pic14_emitcode("mov","ov,c");
7698   /* if it is only one byte then */
7699   if (size == 1) {
7700     l = aopGet(AOP(left),0,FALSE,FALSE);
7701     MOVA(l);
7702     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7703     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7704     pic14_emitcode("mov","c,ov");
7705     pic14_emitcode("rrc","a");
7706     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7707     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7708     aopPut(AOP(result),"a",0);
7709     goto release ;
7710   }
7711
7712   reAdjustPreg(AOP(result));
7713   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7714   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7715   pic14_emitcode("mov","c,ov");
7716   while (size--) {
7717     l = aopGet(AOP(result),offset,FALSE,FALSE);
7718     MOVA(l);
7719     pic14_emitcode("rrc","a");         
7720     aopPut(AOP(result),"a",offset--);
7721   }
7722   reAdjustPreg(AOP(result));
7723   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7724   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7725
7726  release:
7727 #endif
7728
7729   freeAsmop(left,NULL,ic,TRUE);
7730   freeAsmop(result,NULL,ic,TRUE);
7731   freeAsmop(right,NULL,ic,TRUE);
7732 }
7733
7734 /*-----------------------------------------------------------------*/
7735 /* genRightShift - generate code for right shifting                */
7736 /*-----------------------------------------------------------------*/
7737 static void genRightShift (iCode *ic)
7738 {
7739     operand *right, *left, *result;
7740     sym_link *retype ;
7741     int size, offset;
7742     char *l;
7743     symbol *tlbl, *tlbl1 ;
7744
7745     /* if signed then we do it the hard way preserve the
7746     sign bit moving it inwards */
7747     retype = getSpec(operandType(IC_RESULT(ic)));
7748     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7749
7750     if (!SPEC_USIGN(retype)) {
7751         genSignedRightShift (ic);
7752         return ;
7753     }
7754
7755     /* signed & unsigned types are treated the same : i.e. the
7756     signed is NOT propagated inwards : quoting from the
7757     ANSI - standard : "for E1 >> E2, is equivalent to division
7758     by 2**E2 if unsigned or if it has a non-negative value,
7759     otherwise the result is implementation defined ", MY definition
7760     is that the sign does not get propagated */
7761
7762     right = IC_RIGHT(ic);
7763     left  = IC_LEFT(ic);
7764     result = IC_RESULT(ic);
7765
7766     aopOp(right,ic,FALSE);
7767
7768     /* if the shift count is known then do it 
7769     as efficiently as possible */
7770     if (AOP_TYPE(right) == AOP_LIT) {
7771         genRightShiftLiteral (left,right,result,ic, 0);
7772         return ;
7773     }
7774
7775     /* shift count is unknown then we have to form 
7776     a loop get the loop count in B : Note: we take
7777     only the lower order byte since shifting
7778     more that 32 bits make no sense anyway, ( the
7779     largest size of an object can be only 32 bits ) */  
7780
7781     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7782     pic14_emitcode("inc","b");
7783     aopOp(left,ic,FALSE);
7784     aopOp(result,ic,FALSE);
7785
7786     /* now move the left to the result if they are not the
7787     same */
7788     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7789         AOP_SIZE(result) > 1) {
7790
7791         size = AOP_SIZE(result);
7792         offset=0;
7793         while (size--) {
7794             l = aopGet(AOP(left),offset,FALSE,TRUE);
7795             if (*l == '@' && IS_AOP_PREG(result)) {
7796
7797                 pic14_emitcode("mov","a,%s",l);
7798                 aopPut(AOP(result),"a",offset);
7799             } else
7800                 aopPut(AOP(result),l,offset);
7801             offset++;
7802         }
7803     }
7804
7805     tlbl = newiTempLabel(NULL);
7806     tlbl1= newiTempLabel(NULL);
7807     size = AOP_SIZE(result);
7808     offset = size - 1;
7809
7810     /* if it is only one byte then */
7811     if (size == 1) {
7812
7813       tlbl = newiTempLabel(NULL);
7814       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7815         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7816         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7817       }
7818
7819       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7820       emitpcode(POC_RLF,    popGet(AOP(result),0));
7821       emitpLabel(tlbl->key);
7822       emitpcode(POC_RRF,    popGet(AOP(result),0));
7823       emitpcode(POC_ADDLW,  popGetLit(1));
7824       emitSKPC;
7825       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7826
7827       goto release ;
7828     }
7829
7830     reAdjustPreg(AOP(result));
7831     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7832     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7833     CLRC;
7834     while (size--) {
7835         l = aopGet(AOP(result),offset,FALSE,FALSE);
7836         MOVA(l);
7837         pic14_emitcode("rrc","a");         
7838         aopPut(AOP(result),"a",offset--);
7839     }
7840     reAdjustPreg(AOP(result));
7841
7842     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7843     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7844
7845 release:
7846     freeAsmop(left,NULL,ic,TRUE);
7847     freeAsmop (right,NULL,ic,TRUE);
7848     freeAsmop(result,NULL,ic,TRUE);
7849 }
7850
7851 /*-----------------------------------------------------------------*/
7852 /* genUnpackBits - generates code for unpacking bits               */
7853 /*-----------------------------------------------------------------*/
7854 static void genUnpackBits (operand *result, char *rname, int ptype)
7855 {    
7856     int shCnt ;
7857     int rlen = 0 ;
7858     sym_link *etype;
7859     int offset = 0 ;
7860
7861     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7862     etype = getSpec(operandType(result));
7863
7864     /* read the first byte  */
7865     switch (ptype) {
7866
7867     case POINTER:
7868     case IPOINTER:
7869         pic14_emitcode("mov","a,@%s",rname);
7870         break;
7871         
7872     case PPOINTER:
7873         pic14_emitcode("movx","a,@%s",rname);
7874         break;
7875         
7876     case FPOINTER:
7877         pic14_emitcode("movx","a,@dptr");
7878         break;
7879
7880     case CPOINTER:
7881         pic14_emitcode("clr","a");
7882         pic14_emitcode("movc","a","@a+dptr");
7883         break;
7884
7885     case GPOINTER:
7886         pic14_emitcode("lcall","__gptrget");
7887         break;
7888     }
7889
7890     /* if we have bitdisplacement then it fits   */
7891     /* into this byte completely or if length is */
7892     /* less than a byte                          */
7893     if ((shCnt = SPEC_BSTR(etype)) || 
7894         (SPEC_BLEN(etype) <= 8))  {
7895
7896         /* shift right acc */
7897         AccRsh(shCnt);
7898
7899         pic14_emitcode("anl","a,#0x%02x",
7900                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7901         aopPut(AOP(result),"a",offset);
7902         return ;
7903     }
7904
7905     /* bit field did not fit in a byte  */
7906     rlen = SPEC_BLEN(etype) - 8;
7907     aopPut(AOP(result),"a",offset++);
7908
7909     while (1)  {
7910
7911         switch (ptype) {
7912         case POINTER:
7913         case IPOINTER:
7914             pic14_emitcode("inc","%s",rname);
7915             pic14_emitcode("mov","a,@%s",rname);
7916             break;
7917             
7918         case PPOINTER:
7919             pic14_emitcode("inc","%s",rname);
7920             pic14_emitcode("movx","a,@%s",rname);
7921             break;
7922
7923         case FPOINTER:
7924             pic14_emitcode("inc","dptr");
7925             pic14_emitcode("movx","a,@dptr");
7926             break;
7927             
7928         case CPOINTER:
7929             pic14_emitcode("clr","a");
7930             pic14_emitcode("inc","dptr");
7931             pic14_emitcode("movc","a","@a+dptr");
7932             break;
7933             
7934         case GPOINTER:
7935             pic14_emitcode("inc","dptr");
7936             pic14_emitcode("lcall","__gptrget");
7937             break;
7938         }
7939
7940         rlen -= 8;            
7941         /* if we are done */
7942         if ( rlen <= 0 )
7943             break ;
7944         
7945         aopPut(AOP(result),"a",offset++);
7946                               
7947     }
7948     
7949     if (rlen) {
7950         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7951         aopPut(AOP(result),"a",offset);        
7952     }
7953     
7954     return ;
7955 }
7956
7957 #if 0
7958 /*-----------------------------------------------------------------*/
7959 /* genDataPointerGet - generates code when ptr offset is known     */
7960 /*-----------------------------------------------------------------*/
7961 static void genDataPointerGet (operand *left, 
7962                                operand *result, 
7963                                iCode *ic)
7964 {
7965   int size , offset = 0;
7966
7967
7968   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7969
7970
7971   /* optimization - most of the time, left and result are the same
7972    * address, but different types. for the pic code, we could omit
7973    * the following
7974    */
7975
7976   aopOp(result,ic,TRUE);
7977
7978   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7979
7980   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7981
7982   size = AOP_SIZE(result);
7983
7984   while (size--) {
7985     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7986     offset++;
7987   }
7988
7989   freeAsmop(left,NULL,ic,TRUE);
7990   freeAsmop(result,NULL,ic,TRUE);
7991 }
7992 #endif
7993 /*-----------------------------------------------------------------*/
7994 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7995 /*-----------------------------------------------------------------*/
7996 static void genNearPointerGet (operand *left, 
7997                                operand *result, 
7998                                iCode *ic)
7999 {
8000     asmop *aop = NULL;
8001     //regs *preg = NULL ;
8002     char *rname ;
8003     sym_link *rtype, *retype;
8004     sym_link *ltype = operandType(left);    
8005     //char buffer[80];
8006
8007     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8008
8009     rtype = operandType(result);
8010     retype= getSpec(rtype);
8011     
8012     aopOp(left,ic,FALSE);
8013     
8014     /* if left is rematerialisable and
8015        result is not bit variable type and
8016        the left is pointer to data space i.e
8017        lower 128 bytes of space */
8018     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8019         !IS_BITVAR(retype)         &&
8020         DCL_TYPE(ltype) == POINTER) {
8021       //genDataPointerGet (left,result,ic);
8022         return ;
8023     }
8024     
8025     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8026
8027         /* if the value is already in a pointer register
8028        then don't need anything more */
8029     if (!AOP_INPREG(AOP(left))) {
8030         /* otherwise get a free pointer register */
8031     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8032 /*
8033         aop = newAsmop(0);
8034         preg = getFreePtr(ic,&aop,FALSE);
8035         pic14_emitcode("mov","%s,%s",
8036                 preg->name,
8037                 aopGet(AOP(left),0,FALSE,TRUE));
8038         rname = preg->name ;
8039 */
8040     rname ="BAD";
8041     } else
8042         rname = aopGet(AOP(left),0,FALSE,FALSE);
8043     
8044     aopOp (result,ic,FALSE);
8045     
8046       /* if bitfield then unpack the bits */
8047     if (IS_BITVAR(retype)) 
8048         genUnpackBits (result,rname,POINTER);
8049     else {
8050         /* we have can just get the values */
8051       int size = AOP_SIZE(result);
8052       int offset = 0 ;  
8053         
8054       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8055
8056       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8057       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8058       while(size--) {
8059         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8060         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8061         if(size)
8062           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8063       }
8064 /*
8065         while (size--) {
8066             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8067
8068                 pic14_emitcode("mov","a,@%s",rname);
8069                 aopPut(AOP(result),"a",offset);
8070             } else {
8071                 sprintf(buffer,"@%s",rname);
8072                 aopPut(AOP(result),buffer,offset);
8073             }
8074             offset++ ;
8075             if (size)
8076                 pic14_emitcode("inc","%s",rname);
8077         }
8078 */
8079     }
8080
8081     /* now some housekeeping stuff */
8082     if (aop) {
8083         /* we had to allocate for this iCode */
8084     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8085         freeAsmop(NULL,aop,ic,TRUE);
8086     } else { 
8087         /* we did not allocate which means left
8088            already in a pointer register, then
8089            if size > 0 && this could be used again
8090            we have to point it back to where it 
8091            belongs */
8092     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8093         if (AOP_SIZE(result) > 1 &&
8094             !OP_SYMBOL(left)->remat &&
8095             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8096               ic->depth )) {
8097             int size = AOP_SIZE(result) - 1;
8098             while (size--)
8099                 pic14_emitcode("dec","%s",rname);
8100         }
8101     }
8102
8103     /* done */
8104     freeAsmop(left,NULL,ic,TRUE);
8105     freeAsmop(result,NULL,ic,TRUE);
8106      
8107 }
8108
8109 /*-----------------------------------------------------------------*/
8110 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8111 /*-----------------------------------------------------------------*/
8112 static void genPagedPointerGet (operand *left, 
8113                                operand *result, 
8114                                iCode *ic)
8115 {
8116     asmop *aop = NULL;
8117     regs *preg = NULL ;
8118     char *rname ;
8119     sym_link *rtype, *retype;    
8120
8121     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8122
8123     rtype = operandType(result);
8124     retype= getSpec(rtype);
8125     
8126     aopOp(left,ic,FALSE);
8127
8128   /* if the value is already in a pointer register
8129        then don't need anything more */
8130     if (!AOP_INPREG(AOP(left))) {
8131         /* otherwise get a free pointer register */
8132         aop = newAsmop(0);
8133         preg = getFreePtr(ic,&aop,FALSE);
8134         pic14_emitcode("mov","%s,%s",
8135                 preg->name,
8136                 aopGet(AOP(left),0,FALSE,TRUE));
8137         rname = preg->name ;
8138     } else
8139         rname = aopGet(AOP(left),0,FALSE,FALSE);
8140     
8141     freeAsmop(left,NULL,ic,TRUE);
8142     aopOp (result,ic,FALSE);
8143
8144     /* if bitfield then unpack the bits */
8145     if (IS_BITVAR(retype)) 
8146         genUnpackBits (result,rname,PPOINTER);
8147     else {
8148         /* we have can just get the values */
8149         int size = AOP_SIZE(result);
8150         int offset = 0 ;        
8151         
8152         while (size--) {
8153             
8154             pic14_emitcode("movx","a,@%s",rname);
8155             aopPut(AOP(result),"a",offset);
8156             
8157             offset++ ;
8158             
8159             if (size)
8160                 pic14_emitcode("inc","%s",rname);
8161         }
8162     }
8163
8164     /* now some housekeeping stuff */
8165     if (aop) {
8166         /* we had to allocate for this iCode */
8167         freeAsmop(NULL,aop,ic,TRUE);
8168     } else { 
8169         /* we did not allocate which means left
8170            already in a pointer register, then
8171            if size > 0 && this could be used again
8172            we have to point it back to where it 
8173            belongs */
8174         if (AOP_SIZE(result) > 1 &&
8175             !OP_SYMBOL(left)->remat &&
8176             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8177               ic->depth )) {
8178             int size = AOP_SIZE(result) - 1;
8179             while (size--)
8180                 pic14_emitcode("dec","%s",rname);
8181         }
8182     }
8183
8184     /* done */
8185     freeAsmop(result,NULL,ic,TRUE);
8186     
8187         
8188 }
8189
8190 /*-----------------------------------------------------------------*/
8191 /* genFarPointerGet - gget value from far space                    */
8192 /*-----------------------------------------------------------------*/
8193 static void genFarPointerGet (operand *left,
8194                               operand *result, iCode *ic)
8195 {
8196     int size, offset ;
8197     sym_link *retype = getSpec(operandType(result));
8198
8199     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8200
8201     aopOp(left,ic,FALSE);
8202
8203     /* if the operand is already in dptr 
8204     then we do nothing else we move the value to dptr */
8205     if (AOP_TYPE(left) != AOP_STR) {
8206         /* if this is remateriazable */
8207         if (AOP_TYPE(left) == AOP_IMMD)
8208             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8209         else { /* we need to get it byte by byte */
8210             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8211             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8212             if (options.model == MODEL_FLAT24)
8213             {
8214                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8215             }
8216         }
8217     }
8218     /* so dptr know contains the address */
8219     freeAsmop(left,NULL,ic,TRUE);
8220     aopOp(result,ic,FALSE);
8221
8222     /* if bit then unpack */
8223     if (IS_BITVAR(retype)) 
8224         genUnpackBits(result,"dptr",FPOINTER);
8225     else {
8226         size = AOP_SIZE(result);
8227         offset = 0 ;
8228
8229         while (size--) {
8230             pic14_emitcode("movx","a,@dptr");
8231             aopPut(AOP(result),"a",offset++);
8232             if (size)
8233                 pic14_emitcode("inc","dptr");
8234         }
8235     }
8236
8237     freeAsmop(result,NULL,ic,TRUE);
8238 }
8239 #if 0
8240 /*-----------------------------------------------------------------*/
8241 /* genCodePointerGet - get value from code space                  */
8242 /*-----------------------------------------------------------------*/
8243 static void genCodePointerGet (operand *left,
8244                                 operand *result, iCode *ic)
8245 {
8246     int size, offset ;
8247     sym_link *retype = getSpec(operandType(result));
8248
8249     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8250
8251     aopOp(left,ic,FALSE);
8252
8253     /* if the operand is already in dptr 
8254     then we do nothing else we move the value to dptr */
8255     if (AOP_TYPE(left) != AOP_STR) {
8256         /* if this is remateriazable */
8257         if (AOP_TYPE(left) == AOP_IMMD)
8258             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8259         else { /* we need to get it byte by byte */
8260             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8261             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8262             if (options.model == MODEL_FLAT24)
8263             {
8264                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8265             }
8266         }
8267     }
8268     /* so dptr know contains the address */
8269     freeAsmop(left,NULL,ic,TRUE);
8270     aopOp(result,ic,FALSE);
8271
8272     /* if bit then unpack */
8273     if (IS_BITVAR(retype)) 
8274         genUnpackBits(result,"dptr",CPOINTER);
8275     else {
8276         size = AOP_SIZE(result);
8277         offset = 0 ;
8278
8279         while (size--) {
8280             pic14_emitcode("clr","a");
8281             pic14_emitcode("movc","a,@a+dptr");
8282             aopPut(AOP(result),"a",offset++);
8283             if (size)
8284                 pic14_emitcode("inc","dptr");
8285         }
8286     }
8287
8288     freeAsmop(result,NULL,ic,TRUE);
8289 }
8290 #endif
8291 /*-----------------------------------------------------------------*/
8292 /* genGenPointerGet - gget value from generic pointer space        */
8293 /*-----------------------------------------------------------------*/
8294 static void genGenPointerGet (operand *left,
8295                               operand *result, iCode *ic)
8296 {
8297   int size, offset ;
8298   sym_link *retype = getSpec(operandType(result));
8299
8300   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8301   aopOp(left,ic,FALSE);
8302   aopOp(result,ic,FALSE);
8303
8304
8305   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8306
8307   /* if the operand is already in dptr 
8308      then we do nothing else we move the value to dptr */
8309   //  if (AOP_TYPE(left) != AOP_STR) {
8310     /* if this is remateriazable */
8311     if (AOP_TYPE(left) == AOP_IMMD) {
8312       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8313       pic14_emitcode("mov","b,#%d",pointerCode(retype));
8314     }
8315     else { /* we need to get it byte by byte */
8316
8317       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8318       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8319
8320       size = AOP_SIZE(result);
8321       offset = 0 ;
8322
8323       while(size--) {
8324         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8325         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8326         if(size)
8327           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8328       }
8329       goto release;
8330     }
8331     //}
8332   /* so dptr know contains the address */
8333
8334   /* if bit then unpack */
8335   //if (IS_BITVAR(retype)) 
8336   //  genUnpackBits(result,"dptr",GPOINTER);
8337
8338  release:
8339   freeAsmop(left,NULL,ic,TRUE);
8340   freeAsmop(result,NULL,ic,TRUE);
8341
8342 }
8343
8344 /*-----------------------------------------------------------------*/
8345 /* genConstPointerGet - get value from const generic pointer space */
8346 /*-----------------------------------------------------------------*/
8347 static void genConstPointerGet (operand *left,
8348                                 operand *result, iCode *ic)
8349 {
8350   //sym_link *retype = getSpec(operandType(result));
8351   symbol *albl = newiTempLabel(NULL);
8352   symbol *blbl = newiTempLabel(NULL);
8353   PIC_OPCODE poc;
8354
8355   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8356   aopOp(left,ic,FALSE);
8357   aopOp(result,ic,FALSE);
8358
8359
8360   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8361
8362   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8363
8364   emitpcode(POC_CALL,popGetLabel(albl->key));
8365   emitpcode(POC_GOTO,popGetLabel(blbl->key));
8366   emitpLabel(albl->key);
8367
8368   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8369     
8370   emitpcode(poc,popGet(AOP(left),1));
8371   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8372   emitpcode(poc,popGet(AOP(left),0));
8373   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8374
8375   emitpLabel(blbl->key);
8376
8377   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8378
8379
8380   freeAsmop(left,NULL,ic,TRUE);
8381   freeAsmop(result,NULL,ic,TRUE);
8382
8383 }
8384 /*-----------------------------------------------------------------*/
8385 /* genPointerGet - generate code for pointer get                   */
8386 /*-----------------------------------------------------------------*/
8387 static void genPointerGet (iCode *ic)
8388 {
8389     operand *left, *result ;
8390     sym_link *type, *etype;
8391     int p_type;
8392
8393     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8394
8395     left = IC_LEFT(ic);
8396     result = IC_RESULT(ic) ;
8397
8398     /* depending on the type of pointer we need to
8399     move it to the correct pointer register */
8400     type = operandType(left);
8401     etype = getSpec(type);
8402
8403     if (IS_PTR_CONST(type))
8404       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8405
8406     /* if left is of type of pointer then it is simple */
8407     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8408         p_type = DCL_TYPE(type);
8409     else {
8410         /* we have to go by the storage class */
8411         p_type = PTR_TYPE(SPEC_OCLS(etype));
8412
8413         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8414
8415         if (SPEC_OCLS(etype)->codesp ) {
8416           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8417           //p_type = CPOINTER ; 
8418         }
8419         else
8420             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8421               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8422                /*p_type = FPOINTER ;*/ 
8423             else
8424                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8425                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8426 /*                  p_type = PPOINTER; */
8427                 else
8428                     if (SPEC_OCLS(etype) == idata )
8429                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8430 /*                      p_type = IPOINTER; */
8431                     else
8432                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8433 /*                      p_type = POINTER ; */
8434     }
8435
8436     /* now that we have the pointer type we assign
8437     the pointer values */
8438     switch (p_type) {
8439
8440     case POINTER:       
8441     case IPOINTER:
8442         genNearPointerGet (left,result,ic);
8443         break;
8444
8445     case PPOINTER:
8446         genPagedPointerGet(left,result,ic);
8447         break;
8448
8449     case FPOINTER:
8450         genFarPointerGet (left,result,ic);
8451         break;
8452
8453     case CPOINTER:
8454         genConstPointerGet (left,result,ic);
8455         //pic14_emitcodePointerGet (left,result,ic);
8456         break;
8457
8458     case GPOINTER:
8459       if (IS_PTR_CONST(type))
8460         genConstPointerGet (left,result,ic);
8461       else
8462         genGenPointerGet (left,result,ic);
8463       break;
8464     }
8465
8466 }
8467
8468 /*-----------------------------------------------------------------*/
8469 /* genPackBits - generates code for packed bit storage             */
8470 /*-----------------------------------------------------------------*/
8471 static void genPackBits (sym_link    *etype ,
8472                          operand *right ,
8473                          char *rname, int p_type)
8474 {
8475     int shCount = 0 ;
8476     int offset = 0  ;
8477     int rLen = 0 ;
8478     int blen, bstr ;   
8479     char *l ;
8480
8481     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8482     blen = SPEC_BLEN(etype);
8483     bstr = SPEC_BSTR(etype);
8484
8485     l = aopGet(AOP(right),offset++,FALSE,FALSE);
8486     MOVA(l);   
8487
8488     /* if the bit lenth is less than or    */
8489     /* it exactly fits a byte then         */
8490     if (SPEC_BLEN(etype) <= 8 )  {
8491         shCount = SPEC_BSTR(etype) ;
8492
8493         /* shift left acc */
8494         AccLsh(shCount);
8495
8496         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8497
8498
8499             switch (p_type) {
8500                 case POINTER:
8501                     pic14_emitcode ("mov","b,a");
8502                     pic14_emitcode("mov","a,@%s",rname);
8503                     break;
8504
8505                 case FPOINTER:
8506                     pic14_emitcode ("mov","b,a");
8507                     pic14_emitcode("movx","a,@dptr");
8508                     break;
8509
8510                 case GPOINTER:
8511                     pic14_emitcode ("push","b");
8512                     pic14_emitcode ("push","acc");
8513                     pic14_emitcode ("lcall","__gptrget");
8514                     pic14_emitcode ("pop","b");
8515                     break;
8516             }
8517
8518             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8519                       ((unsigned char)(0xFF << (blen+bstr)) | 
8520                        (unsigned char)(0xFF >> (8-bstr)) ) );
8521             pic14_emitcode ("orl","a,b");
8522             if (p_type == GPOINTER)
8523                 pic14_emitcode("pop","b");
8524         }
8525     }
8526
8527     switch (p_type) {
8528         case POINTER:
8529             pic14_emitcode("mov","@%s,a",rname);
8530             break;
8531
8532         case FPOINTER:
8533             pic14_emitcode("movx","@dptr,a");
8534             break;
8535
8536         case GPOINTER:
8537             DEBUGpic14_emitcode(";lcall","__gptrput");
8538             break;
8539     }
8540
8541     /* if we r done */
8542     if ( SPEC_BLEN(etype) <= 8 )
8543         return ;
8544
8545     pic14_emitcode("inc","%s",rname);
8546     rLen = SPEC_BLEN(etype) ;     
8547
8548     /* now generate for lengths greater than one byte */
8549     while (1) {
8550
8551         l = aopGet(AOP(right),offset++,FALSE,TRUE);
8552
8553         rLen -= 8 ;
8554         if (rLen <= 0 )
8555             break ;
8556
8557         switch (p_type) {
8558             case POINTER:
8559                 if (*l == '@') {
8560                     MOVA(l);
8561                     pic14_emitcode("mov","@%s,a",rname);
8562                 } else
8563                     pic14_emitcode("mov","@%s,%s",rname,l);
8564                 break;
8565
8566             case FPOINTER:
8567                 MOVA(l);
8568                 pic14_emitcode("movx","@dptr,a");
8569                 break;
8570
8571             case GPOINTER:
8572                 MOVA(l);
8573                 DEBUGpic14_emitcode(";lcall","__gptrput");
8574                 break;  
8575         }   
8576         pic14_emitcode ("inc","%s",rname);
8577     }
8578
8579     MOVA(l);
8580
8581     /* last last was not complete */
8582     if (rLen)   {
8583         /* save the byte & read byte */
8584         switch (p_type) {
8585             case POINTER:
8586                 pic14_emitcode ("mov","b,a");
8587                 pic14_emitcode("mov","a,@%s",rname);
8588                 break;
8589
8590             case FPOINTER:
8591                 pic14_emitcode ("mov","b,a");
8592                 pic14_emitcode("movx","a,@dptr");
8593                 break;
8594
8595             case GPOINTER:
8596                 pic14_emitcode ("push","b");
8597                 pic14_emitcode ("push","acc");
8598                 pic14_emitcode ("lcall","__gptrget");
8599                 pic14_emitcode ("pop","b");
8600                 break;
8601         }
8602
8603         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8604         pic14_emitcode ("orl","a,b");
8605     }
8606
8607     if (p_type == GPOINTER)
8608         pic14_emitcode("pop","b");
8609
8610     switch (p_type) {
8611
8612     case POINTER:
8613         pic14_emitcode("mov","@%s,a",rname);
8614         break;
8615         
8616     case FPOINTER:
8617         pic14_emitcode("movx","@dptr,a");
8618         break;
8619         
8620     case GPOINTER:
8621         DEBUGpic14_emitcode(";lcall","__gptrput");
8622         break;                  
8623     }
8624 }
8625 /*-----------------------------------------------------------------*/
8626 /* genDataPointerSet - remat pointer to data space                 */
8627 /*-----------------------------------------------------------------*/
8628 static void genDataPointerSet(operand *right,
8629                               operand *result,
8630                               iCode *ic)
8631 {
8632     int size, offset = 0 ;
8633     char *l, buffer[256];
8634
8635     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8636     aopOp(right,ic,FALSE);
8637     
8638     l = aopGet(AOP(result),0,FALSE,TRUE);
8639     size = AOP_SIZE(right);
8640 /*
8641     if ( AOP_TYPE(result) == AOP_PCODE) {
8642       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8643               AOP(result)->aopu.pcop->name,
8644               PCOI(AOP(result)->aopu.pcop)->offset);
8645     }
8646 */
8647
8648     // tsd, was l+1 - the underline `_' prefix was being stripped
8649     while (size--) {
8650       if (offset) {
8651         sprintf(buffer,"(%s + %d)",l,offset);
8652         fprintf(stderr,"oops  %s\n",buffer);
8653       } else
8654         sprintf(buffer,"%s",l);
8655
8656         if (AOP_TYPE(right) == AOP_LIT) {
8657           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8658           lit = lit >> (8*offset);
8659           if(lit&0xff) {
8660             pic14_emitcode("movlw","%d",lit);
8661             pic14_emitcode("movwf","%s",buffer);
8662
8663             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8664             //emitpcode(POC_MOVWF, popRegFromString(buffer));
8665             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8666
8667           } else {
8668             pic14_emitcode("clrf","%s",buffer);
8669             //emitpcode(POC_CLRF, popRegFromString(buffer));
8670             emitpcode(POC_CLRF, popGet(AOP(result),0));
8671           }
8672         }else {
8673           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8674           pic14_emitcode("movwf","%s",buffer);
8675
8676           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8677           //emitpcode(POC_MOVWF, popRegFromString(buffer));
8678           emitpcode(POC_MOVWF, popGet(AOP(result),0));
8679
8680         }
8681
8682         offset++;
8683     }
8684
8685     freeAsmop(right,NULL,ic,TRUE);
8686     freeAsmop(result,NULL,ic,TRUE);
8687 }
8688
8689 /*-----------------------------------------------------------------*/
8690 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8691 /*-----------------------------------------------------------------*/
8692 static void genNearPointerSet (operand *right,
8693                                operand *result, 
8694                                iCode *ic)
8695 {
8696   asmop *aop = NULL;
8697   char *l;
8698   sym_link *retype;
8699   sym_link *ptype = operandType(result);
8700
8701     
8702   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8703   retype= getSpec(operandType(right));
8704
8705   aopOp(result,ic,FALSE);
8706
8707     
8708   /* if the result is rematerializable &
8709      in data space & not a bit variable */
8710   //if (AOP_TYPE(result) == AOP_IMMD &&
8711   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8712       DCL_TYPE(ptype) == POINTER   &&
8713       !IS_BITVAR(retype)) {
8714     genDataPointerSet (right,result,ic);
8715     freeAsmop(result,NULL,ic,TRUE);
8716     return;
8717   }
8718
8719   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8720   aopOp(right,ic,FALSE);
8721   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8722
8723   /* if the value is already in a pointer register
8724      then don't need anything more */
8725   if (!AOP_INPREG(AOP(result))) {
8726     /* otherwise get a free pointer register */
8727     //aop = newAsmop(0);
8728     //preg = getFreePtr(ic,&aop,FALSE);
8729     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8730     //pic14_emitcode("mov","%s,%s",
8731     //         preg->name,
8732     //         aopGet(AOP(result),0,FALSE,TRUE));
8733     //rname = preg->name ;
8734     //pic14_emitcode("movwf","fsr");
8735     emitpcode(POC_MOVFW, popGet(AOP(result),0));
8736     emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8737     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8738     emitpcode(POC_MOVWF, popCopyReg(&pc_indf));
8739     goto release;
8740
8741   }// else
8742   //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8743
8744
8745   /* if bitfield then unpack the bits */
8746   if (IS_BITVAR(retype)) {
8747     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8748            "The programmer is obviously confused");
8749     //genPackBits (retype,right,rname,POINTER);
8750     exit(1);
8751   }
8752   else {
8753     /* we have can just get the values */
8754     int size = AOP_SIZE(right);
8755     int offset = 0 ;    
8756
8757     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8758     while (size--) {
8759       l = aopGet(AOP(right),offset,FALSE,TRUE);
8760       if (*l == '@' ) {
8761         //MOVA(l);
8762         //pic14_emitcode("mov","@%s,a",rname);
8763         pic14_emitcode("movf","indf,w ;1");
8764       } else {
8765
8766         if (AOP_TYPE(right) == AOP_LIT) {
8767           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8768           if(lit) {
8769             pic14_emitcode("movlw","%s",l);
8770             pic14_emitcode("movwf","indf ;2");
8771           } else 
8772             pic14_emitcode("clrf","indf");
8773         }else {
8774           pic14_emitcode("movf","%s,w",l);
8775           pic14_emitcode("movwf","indf ;2");
8776         }
8777         //pic14_emitcode("mov","@%s,%s",rname,l);
8778       }
8779       if (size)
8780         pic14_emitcode("incf","fsr,f ;3");
8781       //pic14_emitcode("inc","%s",rname);
8782       offset++;
8783     }
8784   }
8785
8786   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8787   /* now some housekeeping stuff */
8788   if (aop) {
8789     /* we had to allocate for this iCode */
8790     freeAsmop(NULL,aop,ic,TRUE);
8791   } else { 
8792     /* we did not allocate which means left
8793        already in a pointer register, then
8794        if size > 0 && this could be used again
8795        we have to point it back to where it 
8796        belongs */
8797     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8798     if (AOP_SIZE(right) > 1 &&
8799         !OP_SYMBOL(result)->remat &&
8800         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8801           ic->depth )) {
8802       int size = AOP_SIZE(right) - 1;
8803       while (size--)
8804         pic14_emitcode("decf","fsr,f");
8805       //pic14_emitcode("dec","%s",rname);
8806     }
8807   }
8808
8809   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8810   /* done */
8811  release:
8812   freeAsmop(right,NULL,ic,TRUE);
8813   freeAsmop(result,NULL,ic,TRUE);
8814 }
8815
8816 /*-----------------------------------------------------------------*/
8817 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8818 /*-----------------------------------------------------------------*/
8819 static void genPagedPointerSet (operand *right,
8820                                operand *result, 
8821                                iCode *ic)
8822 {
8823     asmop *aop = NULL;
8824     regs *preg = NULL ;
8825     char *rname , *l;
8826     sym_link *retype;
8827        
8828     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8829
8830     retype= getSpec(operandType(right));
8831     
8832     aopOp(result,ic,FALSE);
8833     
8834     /* if the value is already in a pointer register
8835        then don't need anything more */
8836     if (!AOP_INPREG(AOP(result))) {
8837         /* otherwise get a free pointer register */
8838         aop = newAsmop(0);
8839         preg = getFreePtr(ic,&aop,FALSE);
8840         pic14_emitcode("mov","%s,%s",
8841                 preg->name,
8842                 aopGet(AOP(result),0,FALSE,TRUE));
8843         rname = preg->name ;
8844     } else
8845         rname = aopGet(AOP(result),0,FALSE,FALSE);
8846     
8847     freeAsmop(result,NULL,ic,TRUE);
8848     aopOp (right,ic,FALSE);
8849
8850     /* if bitfield then unpack the bits */
8851     if (IS_BITVAR(retype)) 
8852         genPackBits (retype,right,rname,PPOINTER);
8853     else {
8854         /* we have can just get the values */
8855         int size = AOP_SIZE(right);
8856         int offset = 0 ;        
8857         
8858         while (size--) {
8859             l = aopGet(AOP(right),offset,FALSE,TRUE);
8860             
8861             MOVA(l);
8862             pic14_emitcode("movx","@%s,a",rname);
8863
8864             if (size)
8865                 pic14_emitcode("inc","%s",rname);
8866
8867             offset++;
8868         }
8869     }
8870     
8871     /* now some housekeeping stuff */
8872     if (aop) {
8873         /* we had to allocate for this iCode */
8874         freeAsmop(NULL,aop,ic,TRUE);
8875     } else { 
8876         /* we did not allocate which means left
8877            already in a pointer register, then
8878            if size > 0 && this could be used again
8879            we have to point it back to where it 
8880            belongs */
8881         if (AOP_SIZE(right) > 1 &&
8882             !OP_SYMBOL(result)->remat &&
8883             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8884               ic->depth )) {
8885             int size = AOP_SIZE(right) - 1;
8886             while (size--)
8887                 pic14_emitcode("dec","%s",rname);
8888         }
8889     }
8890
8891     /* done */
8892     freeAsmop(right,NULL,ic,TRUE);
8893     
8894         
8895 }
8896
8897 /*-----------------------------------------------------------------*/
8898 /* genFarPointerSet - set value from far space                     */
8899 /*-----------------------------------------------------------------*/
8900 static void genFarPointerSet (operand *right,
8901                               operand *result, iCode *ic)
8902 {
8903     int size, offset ;
8904     sym_link *retype = getSpec(operandType(right));
8905
8906     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8907     aopOp(result,ic,FALSE);
8908
8909     /* if the operand is already in dptr 
8910     then we do nothing else we move the value to dptr */
8911     if (AOP_TYPE(result) != AOP_STR) {
8912         /* if this is remateriazable */
8913         if (AOP_TYPE(result) == AOP_IMMD)
8914             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8915         else { /* we need to get it byte by byte */
8916             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8917             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8918             if (options.model == MODEL_FLAT24)
8919             {
8920                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8921             }
8922         }
8923     }
8924     /* so dptr know contains the address */
8925     freeAsmop(result,NULL,ic,TRUE);
8926     aopOp(right,ic,FALSE);
8927
8928     /* if bit then unpack */
8929     if (IS_BITVAR(retype)) 
8930         genPackBits(retype,right,"dptr",FPOINTER);
8931     else {
8932         size = AOP_SIZE(right);
8933         offset = 0 ;
8934
8935         while (size--) {
8936             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8937             MOVA(l);
8938             pic14_emitcode("movx","@dptr,a");
8939             if (size)
8940                 pic14_emitcode("inc","dptr");
8941         }
8942     }
8943
8944     freeAsmop(right,NULL,ic,TRUE);
8945 }
8946
8947 /*-----------------------------------------------------------------*/
8948 /* genGenPointerSet - set value from generic pointer space         */
8949 /*-----------------------------------------------------------------*/
8950 static void genGenPointerSet (operand *right,
8951                               operand *result, iCode *ic)
8952 {
8953   int size, offset ;
8954   sym_link *retype = getSpec(operandType(right));
8955
8956   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8957
8958   aopOp(result,ic,FALSE);
8959   aopOp(right,ic,FALSE);
8960   size = AOP_SIZE(right);
8961
8962   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8963
8964   /* if the operand is already in dptr 
8965      then we do nothing else we move the value to dptr */
8966   if (AOP_TYPE(result) != AOP_STR) {
8967     /* if this is remateriazable */
8968     if (AOP_TYPE(result) == AOP_IMMD) {
8969       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8970       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8971     }
8972     else { /* we need to get it byte by byte */
8973       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8974       size = AOP_SIZE(right);
8975       offset = 0 ;
8976
8977       /* hack hack! see if this the FSR. If so don't load W */
8978       if(AOP_TYPE(right) != AOP_ACC) {
8979
8980
8981         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8982         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8983
8984         if(AOP_SIZE(result) > 1) {
8985           emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8986           emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8987           emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8988
8989         }
8990
8991         //if(size==2)
8992         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8993         //if(size==4) {
8994         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8995         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8996         //}
8997
8998         while(size--) {
8999           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
9000           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9001           
9002           if(size)
9003             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9004         }
9005
9006
9007         goto release;
9008       } 
9009
9010       if(aopIdx(AOP(result),0) != 4) {
9011
9012         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9013         goto release;
9014       }
9015
9016       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9017       goto release;
9018
9019     }
9020   }
9021   /* so dptr know contains the address */
9022
9023
9024   /* if bit then unpack */
9025   if (IS_BITVAR(retype)) 
9026     genPackBits(retype,right,"dptr",GPOINTER);
9027   else {
9028     size = AOP_SIZE(right);
9029     offset = 0 ;
9030
9031   DEBUGpic14_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9032
9033     while (size--) {
9034
9035       emitpcode(POC_MOVFW,popGet(AOP(result),offset));
9036       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9037
9038       if (AOP_TYPE(right) == AOP_LIT) 
9039         emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9040       else
9041         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9042
9043       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9044
9045       offset++;
9046     }
9047   }
9048
9049  release:
9050   freeAsmop(right,NULL,ic,TRUE);
9051   freeAsmop(result,NULL,ic,TRUE);
9052 }
9053
9054 /*-----------------------------------------------------------------*/
9055 /* genPointerSet - stores the value into a pointer location        */
9056 /*-----------------------------------------------------------------*/
9057 static void genPointerSet (iCode *ic)
9058 {    
9059     operand *right, *result ;
9060     sym_link *type, *etype;
9061     int p_type;
9062
9063     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9064
9065     right = IC_RIGHT(ic);
9066     result = IC_RESULT(ic) ;
9067
9068     /* depending on the type of pointer we need to
9069     move it to the correct pointer register */
9070     type = operandType(result);
9071     etype = getSpec(type);
9072     /* if left is of type of pointer then it is simple */
9073     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9074         p_type = DCL_TYPE(type);
9075     }
9076     else {
9077         /* we have to go by the storage class */
9078         p_type = PTR_TYPE(SPEC_OCLS(etype));
9079
9080 /*      if (SPEC_OCLS(etype)->codesp ) { */
9081 /*          p_type = CPOINTER ;  */
9082 /*      } */
9083 /*      else */
9084 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9085 /*              p_type = FPOINTER ; */
9086 /*          else */
9087 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9088 /*                  p_type = PPOINTER ; */
9089 /*              else */
9090 /*                  if (SPEC_OCLS(etype) == idata ) */
9091 /*                      p_type = IPOINTER ; */
9092 /*                  else */
9093 /*                      p_type = POINTER ; */
9094     }
9095
9096     /* now that we have the pointer type we assign
9097     the pointer values */
9098     switch (p_type) {
9099
9100     case POINTER:
9101     case IPOINTER:
9102         genNearPointerSet (right,result,ic);
9103         break;
9104
9105     case PPOINTER:
9106         genPagedPointerSet (right,result,ic);
9107         break;
9108
9109     case FPOINTER:
9110         genFarPointerSet (right,result,ic);
9111         break;
9112
9113     case GPOINTER:
9114         genGenPointerSet (right,result,ic);
9115         break;
9116
9117     default:
9118       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9119               "genPointerSet: illegal pointer type");
9120     }
9121 }
9122
9123 /*-----------------------------------------------------------------*/
9124 /* genIfx - generate code for Ifx statement                        */
9125 /*-----------------------------------------------------------------*/
9126 static void genIfx (iCode *ic, iCode *popIc)
9127 {
9128   operand *cond = IC_COND(ic);
9129   int isbit =0;
9130
9131   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9132
9133   aopOp(cond,ic,FALSE);
9134
9135   /* get the value into acc */
9136   if (AOP_TYPE(cond) != AOP_CRY)
9137     pic14_toBoolean(cond);
9138   else
9139     isbit = 1;
9140   /* the result is now in the accumulator */
9141   freeAsmop(cond,NULL,ic,TRUE);
9142
9143   /* if there was something to be popped then do it */
9144   if (popIc)
9145     genIpop(popIc);
9146
9147   /* if the condition is  a bit variable */
9148   if (isbit && IS_ITEMP(cond) && 
9149       SPIL_LOC(cond)) {
9150     genIfxJump(ic,SPIL_LOC(cond)->rname);
9151     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9152   }
9153   else {
9154     if (isbit && !IS_ITEMP(cond))
9155       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9156     else
9157       genIfxJump(ic,"a");
9158   }
9159   ic->generated = 1;
9160
9161 }
9162
9163 /*-----------------------------------------------------------------*/
9164 /* genAddrOf - generates code for address of                       */
9165 /*-----------------------------------------------------------------*/
9166 static void genAddrOf (iCode *ic)
9167 {
9168   operand *right, *result, *left;
9169   int size, offset ;
9170
9171   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9172
9173
9174   //aopOp(IC_RESULT(ic),ic,FALSE);
9175
9176   aopOp((left=IC_LEFT(ic)),ic,FALSE);
9177   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9178   aopOp((result=IC_RESULT(ic)),ic,TRUE);
9179
9180   DEBUGpic14_AopType(__LINE__,left,right,result);
9181
9182   size = AOP_SIZE(IC_RESULT(ic));
9183   offset = 0;
9184
9185   while (size--) {
9186     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9187     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9188     offset++;
9189   }
9190
9191   freeAsmop(left,NULL,ic,FALSE);
9192   freeAsmop(result,NULL,ic,TRUE);
9193
9194 }
9195
9196 #if 0
9197 /*-----------------------------------------------------------------*/
9198 /* genFarFarAssign - assignment when both are in far space         */
9199 /*-----------------------------------------------------------------*/
9200 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9201 {
9202     int size = AOP_SIZE(right);
9203     int offset = 0;
9204     char *l ;
9205     /* first push the right side on to the stack */
9206     while (size--) {
9207         l = aopGet(AOP(right),offset++,FALSE,FALSE);
9208         MOVA(l);
9209         pic14_emitcode ("push","acc");
9210     }
9211     
9212     freeAsmop(right,NULL,ic,FALSE);
9213     /* now assign DPTR to result */
9214     aopOp(result,ic,FALSE);
9215     size = AOP_SIZE(result);
9216     while (size--) {
9217         pic14_emitcode ("pop","acc");
9218         aopPut(AOP(result),"a",--offset);
9219     }
9220     freeAsmop(result,NULL,ic,FALSE);
9221         
9222 }
9223 #endif
9224
9225 /*-----------------------------------------------------------------*/
9226 /* genAssign - generate code for assignment                        */
9227 /*-----------------------------------------------------------------*/
9228 static void genAssign (iCode *ic)
9229 {
9230   operand *result, *right;
9231   int size, offset,know_W;
9232   unsigned long lit = 0L;
9233
9234   result = IC_RESULT(ic);
9235   right  = IC_RIGHT(ic) ;
9236
9237   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9238
9239   /* if they are the same */
9240   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9241     return ;
9242
9243   aopOp(right,ic,FALSE);
9244   aopOp(result,ic,TRUE);
9245
9246   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9247
9248   /* if they are the same registers */
9249   if (pic14_sameRegs(AOP(right),AOP(result)))
9250     goto release;
9251
9252   /* if the result is a bit */
9253   if (AOP_TYPE(result) == AOP_CRY) {
9254
9255     /* if the right size is a literal then
9256        we know what the value is */
9257     if (AOP_TYPE(right) == AOP_LIT) {
9258           
9259       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9260                   popGet(AOP(result),0));
9261
9262       if (((int) operandLitValue(right))) 
9263         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9264                        AOP(result)->aopu.aop_dir,
9265                        AOP(result)->aopu.aop_dir);
9266       else
9267         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9268                        AOP(result)->aopu.aop_dir,
9269                        AOP(result)->aopu.aop_dir);
9270       goto release;
9271     }
9272
9273     /* the right is also a bit variable */
9274     if (AOP_TYPE(right) == AOP_CRY) {
9275       emitpcode(POC_BCF,    popGet(AOP(result),0));
9276       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9277       emitpcode(POC_BSF,    popGet(AOP(result),0));
9278
9279       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9280                      AOP(result)->aopu.aop_dir,
9281                      AOP(result)->aopu.aop_dir);
9282       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9283                      AOP(right)->aopu.aop_dir,
9284                      AOP(right)->aopu.aop_dir);
9285       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9286                      AOP(result)->aopu.aop_dir,
9287                      AOP(result)->aopu.aop_dir);
9288       goto release ;
9289     }
9290
9291     /* we need to or */
9292     emitpcode(POC_BCF,    popGet(AOP(result),0));
9293     pic14_toBoolean(right);
9294     emitSKPZ;
9295     emitpcode(POC_BSF,    popGet(AOP(result),0));
9296     //aopPut(AOP(result),"a",0);
9297     goto release ;
9298   }
9299
9300   /* bit variables done */
9301   /* general case */
9302   size = AOP_SIZE(result);
9303   offset = 0 ;
9304   if(AOP_TYPE(right) == AOP_LIT)
9305     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9306
9307   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9308   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9309     if(aopIdx(AOP(result),0) == 4) {
9310   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9311       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9312       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9313       goto release;
9314     } else
9315       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9316   }
9317
9318   know_W=-1;
9319   while (size--) {
9320   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9321     if(AOP_TYPE(right) == AOP_LIT) {
9322       if(lit&0xff) {
9323         if(know_W != (lit&0xff))
9324           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9325         know_W = lit&0xff;
9326         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9327       } else
9328         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9329
9330       lit >>= 8;
9331
9332     } else if (AOP_TYPE(right) == AOP_CRY) {
9333       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9334       if(offset == 0) {
9335         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9336         emitpcode(POC_INCF, popGet(AOP(result),0));
9337       }
9338     } else if (AOP_TYPE(right) == AOP_IMMD) {
9339             DEBUGpic14_emitcode ("; ***","%s  %d AOP_IMMD",__FUNCTION__,__LINE__);
9340             emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9341             emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9342     } else {
9343   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9344       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9345       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9346     }
9347             
9348     offset++;
9349   }
9350
9351     
9352  release:
9353   freeAsmop (right,NULL,ic,FALSE);
9354   freeAsmop (result,NULL,ic,TRUE);
9355 }   
9356
9357 /*-----------------------------------------------------------------*/
9358 /* genJumpTab - genrates code for jump table                       */
9359 /*-----------------------------------------------------------------*/
9360 static void genJumpTab (iCode *ic)
9361 {
9362     symbol *jtab;
9363     char *l;
9364
9365     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9366
9367     aopOp(IC_JTCOND(ic),ic,FALSE);
9368     /* get the condition into accumulator */
9369     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9370     MOVA(l);
9371     /* multiply by three */
9372     pic14_emitcode("add","a,acc");
9373     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9374
9375     jtab = newiTempLabel(NULL);
9376     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9377     pic14_emitcode("jmp","@a+dptr");
9378     pic14_emitcode("","%05d_DS_:",jtab->key+100);
9379
9380     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9381     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9382     emitSKPNC;
9383     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9384     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9385     emitpLabel(jtab->key);
9386
9387     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9388
9389     /* now generate the jump labels */
9390     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9391          jtab = setNextItem(IC_JTLABELS(ic))) {
9392         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9393         emitpcode(POC_GOTO,popGetLabel(jtab->key));
9394         
9395     }
9396
9397 }
9398
9399 /*-----------------------------------------------------------------*/
9400 /* genMixedOperation - gen code for operators between mixed types  */
9401 /*-----------------------------------------------------------------*/
9402 /*
9403   TSD - Written for the PIC port - but this unfortunately is buggy.
9404   This routine is good in that it is able to efficiently promote 
9405   types to different (larger) sizes. Unfortunately, the temporary
9406   variables that are optimized out by this routine are sometimes
9407   used in other places. So until I know how to really parse the 
9408   iCode tree, I'm going to not be using this routine :(.
9409 */
9410 static int genMixedOperation (iCode *ic)
9411 {
9412 #if 0
9413   operand *result = IC_RESULT(ic);
9414   sym_link *ctype = operandType(IC_LEFT(ic));
9415   operand *right = IC_RIGHT(ic);
9416   int ret = 0;
9417   int big,small;
9418   int offset;
9419
9420   iCode *nextic;
9421   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9422
9423   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9424
9425   nextic = ic->next;
9426   if(!nextic)
9427     return 0;
9428
9429   nextright = IC_RIGHT(nextic);
9430   nextleft  = IC_LEFT(nextic);
9431   nextresult = IC_RESULT(nextic);
9432
9433   aopOp(right,ic,FALSE);
9434   aopOp(result,ic,FALSE);
9435   aopOp(nextright,  nextic, FALSE);
9436   aopOp(nextleft,   nextic, FALSE);
9437   aopOp(nextresult, nextic, FALSE);
9438
9439   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9440
9441     operand *t = right;
9442     right = nextright;
9443     nextright = t; 
9444
9445     pic14_emitcode(";remove right +","");
9446
9447   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9448 /*
9449     operand *t = right;
9450     right = nextleft;
9451     nextleft = t; 
9452 */
9453     pic14_emitcode(";remove left +","");
9454   } else
9455     return 0;
9456
9457   big = AOP_SIZE(nextleft);
9458   small = AOP_SIZE(nextright);
9459
9460   switch(nextic->op) {
9461
9462   case '+':
9463     pic14_emitcode(";optimize a +","");
9464     /* if unsigned or not an integral type */
9465     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9466       pic14_emitcode(";add a bit to something","");
9467     } else {
9468
9469       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9470
9471       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9472         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9473         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9474       } else
9475         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9476
9477       offset = 0;
9478       while(--big) {
9479
9480         offset++;
9481
9482         if(--small) {
9483           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9484             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9485             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9486           }
9487
9488           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9489           emitSKPNC;
9490           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9491                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9492                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9493           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9494           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9495
9496         } else {
9497           pic14_emitcode("rlf","known_zero,w");
9498
9499           /*
9500             if right is signed
9501               btfsc  right,7
9502                addlw ff
9503           */
9504           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9505             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9506             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9507           } else {
9508             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9509           }
9510         }
9511       }
9512       ret = 1;
9513     }
9514   }
9515   ret = 1;
9516
9517 release:
9518   freeAsmop(right,NULL,ic,TRUE);
9519   freeAsmop(result,NULL,ic,TRUE);
9520   freeAsmop(nextright,NULL,ic,TRUE);
9521   freeAsmop(nextleft,NULL,ic,TRUE);
9522   if(ret)
9523     nextic->generated = 1;
9524
9525   return ret;
9526 #else
9527   return 0;
9528 #endif
9529 }
9530 /*-----------------------------------------------------------------*/
9531 /* genCast - gen code for casting                                  */
9532 /*-----------------------------------------------------------------*/
9533 static void genCast (iCode *ic)
9534 {
9535     operand *result = IC_RESULT(ic);
9536     sym_link *ctype = operandType(IC_LEFT(ic));
9537     sym_link *rtype = operandType(IC_RIGHT(ic));
9538     operand *right = IC_RIGHT(ic);
9539     int size, offset ;
9540
9541     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9542     /* if they are equivalent then do nothing */
9543     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9544         return ;
9545
9546     aopOp(right,ic,FALSE) ;
9547     aopOp(result,ic,FALSE);
9548
9549     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9550
9551     /* if the result is a bit */
9552     if (AOP_TYPE(result) == AOP_CRY) {
9553         /* if the right size is a literal then
9554         we know what the value is */
9555       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9556         if (AOP_TYPE(right) == AOP_LIT) {
9557
9558           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9559                       popGet(AOP(result),0));
9560
9561             if (((int) operandLitValue(right))) 
9562               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9563                        AOP(result)->aopu.aop_dir,
9564                        AOP(result)->aopu.aop_dir);
9565             else
9566               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9567                        AOP(result)->aopu.aop_dir,
9568                        AOP(result)->aopu.aop_dir);
9569
9570             goto release;
9571         }
9572
9573         /* the right is also a bit variable */
9574         if (AOP_TYPE(right) == AOP_CRY) {
9575
9576           emitCLRC;
9577           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9578
9579           pic14_emitcode("clrc","");
9580           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9581                    AOP(right)->aopu.aop_dir,
9582                    AOP(right)->aopu.aop_dir);
9583             aopPut(AOP(result),"c",0);
9584             goto release ;
9585         }
9586
9587         /* we need to or */
9588         if (AOP_TYPE(right) == AOP_REG) {
9589           emitpcode(POC_BCF,    popGet(AOP(result),0));
9590           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9591           emitpcode(POC_BSF,    popGet(AOP(result),0));
9592         }
9593         pic14_toBoolean(right);
9594         aopPut(AOP(result),"a",0);
9595         goto release ;
9596     }
9597
9598     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9599       int offset = 1;
9600       size = AOP_SIZE(result);
9601
9602       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9603
9604       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9605       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9606       emitpcode(POC_INCF,   popGet(AOP(result),0));
9607
9608       while (size--)
9609         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9610
9611       goto release;
9612     }
9613
9614     /* if they are the same size : or less */
9615     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9616
9617         /* if they are in the same place */
9618       if (pic14_sameRegs(AOP(right),AOP(result)))
9619         goto release;
9620
9621       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9622       if (IS_PTR_CONST(rtype))
9623         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9624       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9625         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9626
9627       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9628         emitpcode(POC_MOVLW, popGet(AOP(right),0));
9629         emitpcode(POC_MOVWF, popGet(AOP(result),0));
9630         emitpcode(POC_MOVLW, popGet(AOP(right),1));
9631         emitpcode(POC_MOVWF, popGet(AOP(result),1));
9632         if(AOP_SIZE(result) <2)
9633           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9634
9635       } else {
9636
9637         /* if they in different places then copy */
9638         size = AOP_SIZE(result);
9639         offset = 0 ;
9640         while (size--) {
9641           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9642           emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9643
9644           //aopPut(AOP(result),
9645           // aopGet(AOP(right),offset,FALSE,FALSE),
9646           // offset);
9647
9648           offset++;
9649         }
9650       }
9651       goto release;
9652     }
9653
9654
9655     /* if the result is of type pointer */
9656     if (IS_PTR(ctype)) {
9657
9658         int p_type;
9659         sym_link *type = operandType(right);
9660         sym_link *etype = getSpec(type);
9661       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9662
9663         /* pointer to generic pointer */
9664         if (IS_GENPTR(ctype)) {
9665             char *l = zero;
9666             
9667             if (IS_PTR(type)) 
9668                 p_type = DCL_TYPE(type);
9669             else {
9670                 /* we have to go by the storage class */
9671                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9672
9673 /*              if (SPEC_OCLS(etype)->codesp )  */
9674 /*                  p_type = CPOINTER ;  */
9675 /*              else */
9676 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9677 /*                      p_type = FPOINTER ; */
9678 /*                  else */
9679 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9680 /*                          p_type = PPOINTER; */
9681 /*                      else */
9682 /*                          if (SPEC_OCLS(etype) == idata ) */
9683 /*                              p_type = IPOINTER ; */
9684 /*                          else */
9685 /*                              p_type = POINTER ; */
9686             }
9687                 
9688             /* the first two bytes are known */
9689       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9690             size = GPTRSIZE - 1; 
9691             offset = 0 ;
9692             while (size--) {
9693               if(offset < AOP_SIZE(right)) {
9694       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9695                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9696                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9697                   emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9698                   emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9699                 } else { 
9700                   aopPut(AOP(result),
9701                          aopGet(AOP(right),offset,FALSE,FALSE),
9702                          offset);
9703                 }
9704               } else 
9705                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9706               offset++;
9707             }
9708             /* the last byte depending on type */
9709             switch (p_type) {
9710             case IPOINTER:
9711             case POINTER:
9712                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9713                 break;
9714             case FPOINTER:
9715               pic14_emitcode(";BUG!? ","%d",__LINE__);
9716                 l = one;
9717                 break;
9718             case CPOINTER:
9719               pic14_emitcode(";BUG!? ","%d",__LINE__);
9720                 l = "#0x02";
9721                 break;                          
9722             case PPOINTER:
9723               pic14_emitcode(";BUG!? ","%d",__LINE__);
9724                 l = "#0x03";
9725                 break;
9726                 
9727             default:
9728                 /* this should never happen */
9729                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9730                        "got unknown pointer type");
9731                 exit(1);
9732             }
9733             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9734             goto release ;
9735         }
9736         
9737         /* just copy the pointers */
9738         size = AOP_SIZE(result);
9739         offset = 0 ;
9740         while (size--) {
9741             aopPut(AOP(result),
9742                    aopGet(AOP(right),offset,FALSE,FALSE),
9743                    offset);
9744             offset++;
9745         }
9746         goto release ;
9747     }
9748     
9749
9750
9751     /* so we now know that the size of destination is greater
9752     than the size of the source.
9753     Now, if the next iCode is an operator then we might be
9754     able to optimize the operation without performing a cast.
9755     */
9756     if(genMixedOperation(ic))
9757       goto release;
9758
9759     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9760     
9761     /* we move to result for the size of source */
9762     size = AOP_SIZE(right);
9763     offset = 0 ;
9764     while (size--) {
9765       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9766       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9767       offset++;
9768     }
9769
9770     /* now depending on the sign of the destination */
9771     size = AOP_SIZE(result) - AOP_SIZE(right);
9772     /* if unsigned or not an integral type */
9773     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9774       while (size--)
9775         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9776     } else {
9777       /* we need to extend the sign :{ */
9778
9779       if(size == 1) {
9780         /* Save one instruction of casting char to int */
9781         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9782         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9783         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9784       } else {
9785         emitpcodeNULLop(POC_CLRW);
9786
9787         if(offset)
9788           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9789         else
9790           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9791         
9792         emitpcode(POC_MOVLW,   popGetLit(0xff));
9793
9794         while (size--)
9795           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9796       }
9797     }
9798
9799 release:
9800     freeAsmop(right,NULL,ic,TRUE);
9801     freeAsmop(result,NULL,ic,TRUE);
9802
9803 }
9804
9805 /*-----------------------------------------------------------------*/
9806 /* genDjnz - generate decrement & jump if not zero instrucion      */
9807 /*-----------------------------------------------------------------*/
9808 static int genDjnz (iCode *ic, iCode *ifx)
9809 {
9810     symbol *lbl, *lbl1;
9811     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9812
9813     if (!ifx)
9814         return 0;
9815     
9816     /* if the if condition has a false label
9817        then we cannot save */
9818     if (IC_FALSE(ifx))
9819         return 0;
9820
9821     /* if the minus is not of the form 
9822        a = a - 1 */
9823     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9824         !IS_OP_LITERAL(IC_RIGHT(ic)))
9825         return 0;
9826
9827     if (operandLitValue(IC_RIGHT(ic)) != 1)
9828         return 0;
9829
9830     /* if the size of this greater than one then no
9831        saving */
9832     if (getSize(operandType(IC_RESULT(ic))) > 1)
9833         return 0;
9834
9835     /* otherwise we can save BIG */
9836     lbl = newiTempLabel(NULL);
9837     lbl1= newiTempLabel(NULL);
9838
9839     aopOp(IC_RESULT(ic),ic,FALSE);
9840     
9841     if (IS_AOP_PREG(IC_RESULT(ic))) {
9842         pic14_emitcode("dec","%s",
9843                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9844         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9845         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9846     } else {    
9847
9848
9849       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9850       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9851
9852       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9853       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9854
9855     }
9856 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9857 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9858 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9859 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9860
9861     
9862     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9863     ifx->generated = 1;
9864     return 1;
9865 }
9866
9867 /*-----------------------------------------------------------------*/
9868 /* genReceive - generate code for a receive iCode                  */
9869 /*-----------------------------------------------------------------*/
9870 static void genReceive (iCode *ic)
9871 {    
9872   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9873
9874   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9875       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9876         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9877
9878     int size = getSize(operandType(IC_RESULT(ic)));
9879     int offset =  fReturnSizePic - size;
9880     while (size--) {
9881       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9882                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9883       offset++;
9884     }
9885     aopOp(IC_RESULT(ic),ic,FALSE);  
9886     size = AOP_SIZE(IC_RESULT(ic));
9887     offset = 0;
9888     while (size--) {
9889       pic14_emitcode ("pop","acc");
9890       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9891     }
9892         
9893   } else {
9894     _G.accInUse++;
9895     aopOp(IC_RESULT(ic),ic,FALSE);  
9896     _G.accInUse--;
9897     assignResultValue(IC_RESULT(ic));   
9898   }
9899
9900   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9901 }
9902
9903 /*-----------------------------------------------------------------*/
9904 /* genpic14Code - generate code for pic14 based controllers        */
9905 /*-----------------------------------------------------------------*/
9906 /*
9907  * At this point, ralloc.c has gone through the iCode and attempted
9908  * to optimize in a way suitable for a PIC. Now we've got to generate
9909  * PIC instructions that correspond to the iCode.
9910  *
9911  * Once the instructions are generated, we'll pass through both the
9912  * peep hole optimizer and the pCode optimizer.
9913  *-----------------------------------------------------------------*/
9914
9915 void genpic14Code (iCode *lic)
9916 {
9917     iCode *ic;
9918     int cln = 0;
9919
9920     lineHead = lineCurr = NULL;
9921
9922     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9923     addpBlock(pb);
9924
9925     /* if debug information required */
9926     if (options.debug && currFunc) { 
9927       if (currFunc) {
9928         debugFile->writeFunction(currFunc);
9929         _G.debugLine = 1;
9930         if (IS_STATIC(currFunc->etype)) {
9931           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9932           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9933         } else {
9934           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9935           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9936         }
9937         _G.debugLine = 0;
9938       }
9939     }
9940
9941
9942     for (ic = lic ; ic ; ic = ic->next ) {
9943
9944       DEBUGpic14_emitcode(";ic","");
9945         if ( cln != ic->lineno ) {
9946             if ( options.debug ) {
9947                 _G.debugLine = 1;
9948                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9949                          FileBaseName(ic->filename),ic->lineno,
9950                          ic->level,ic->block);
9951                 _G.debugLine = 0;
9952             }
9953             /*
9954               pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9955               pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9956               printCLine(ic->filename, ic->lineno));
9957             */
9958             if (!options.noCcodeInAsm) {
9959               addpCode2pBlock(pb,
9960                               newpCodeCSource(ic->lineno, 
9961                                               ic->filename, 
9962                                               printCLine(ic->filename, ic->lineno)));
9963             }
9964
9965             cln = ic->lineno ;
9966         }
9967
9968         // if you want printILine too, look at ../mcs51/gen.c, i don't understand this :)
9969
9970         /* if the result is marked as
9971            spilt and rematerializable or code for
9972            this has already been generated then
9973            do nothing */
9974         if (resultRemat(ic) || ic->generated ) 
9975             continue ;
9976         
9977         /* depending on the operation */
9978         switch (ic->op) {
9979         case '!' :
9980             genNot(ic);
9981             break;
9982             
9983         case '~' :
9984             genCpl(ic);
9985             break;
9986             
9987         case UNARYMINUS:
9988             genUminus (ic);
9989             break;
9990             
9991         case IPUSH:
9992             genIpush (ic);
9993             break;
9994             
9995         case IPOP:
9996             /* IPOP happens only when trying to restore a 
9997                spilt live range, if there is an ifx statement
9998                following this pop then the if statement might
9999                be using some of the registers being popped which
10000                would destory the contents of the register so
10001                we need to check for this condition and handle it */
10002             if (ic->next            && 
10003                 ic->next->op == IFX &&
10004                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10005                 genIfx (ic->next,ic);
10006             else
10007                 genIpop (ic);
10008             break; 
10009             
10010         case CALL:
10011             genCall (ic);
10012             break;
10013             
10014         case PCALL:
10015             genPcall (ic);
10016             break;
10017             
10018         case FUNCTION:
10019             genFunction (ic);
10020             break;
10021             
10022         case ENDFUNCTION:
10023             genEndFunction (ic);
10024             break;
10025             
10026         case RETURN:
10027             genRet (ic);
10028             break;
10029             
10030         case LABEL:
10031             genLabel (ic);
10032             break;
10033             
10034         case GOTO:
10035             genGoto (ic);
10036             break;
10037             
10038         case '+' :
10039             genPlus (ic) ;
10040             break;
10041             
10042         case '-' :
10043             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10044                 genMinus (ic);
10045             break;
10046             
10047         case '*' :
10048             genMult (ic);
10049             break;
10050             
10051         case '/' :
10052             genDiv (ic) ;
10053             break;
10054             
10055         case '%' :
10056             genMod (ic);
10057             break;
10058             
10059         case '>' :
10060             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10061             break;
10062             
10063         case '<' :
10064             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10065             break;
10066             
10067         case LE_OP:
10068         case GE_OP:
10069         case NE_OP:
10070             
10071             /* note these two are xlated by algebraic equivalence
10072                during parsing SDCC.y */
10073             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10074                    "got '>=' or '<=' shouldn't have come here");
10075             break;      
10076             
10077         case EQ_OP:
10078             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10079             break;          
10080             
10081         case AND_OP:
10082             genAndOp (ic);
10083             break;
10084             
10085         case OR_OP:
10086             genOrOp (ic);
10087             break;
10088             
10089         case '^' :
10090             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10091             break;
10092             
10093         case '|' :
10094                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10095             break;
10096             
10097         case BITWISEAND:
10098             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10099             break;
10100             
10101         case INLINEASM:
10102             genInline (ic);
10103             break;
10104             
10105         case RRC:
10106             genRRC (ic);
10107             break;
10108             
10109         case RLC:
10110             genRLC (ic);
10111             break;
10112             
10113         case GETHBIT:
10114             genGetHbit (ic);
10115             break;
10116             
10117         case LEFT_OP:
10118             genLeftShift (ic);
10119             break;
10120             
10121         case RIGHT_OP:
10122             genRightShift (ic);
10123             break;
10124             
10125         case GET_VALUE_AT_ADDRESS:
10126             genPointerGet(ic);
10127             break;
10128             
10129         case '=' :
10130             if (POINTER_SET(ic))
10131                 genPointerSet(ic);
10132             else
10133                 genAssign(ic);
10134             break;
10135             
10136         case IFX:
10137             genIfx (ic,NULL);
10138             break;
10139             
10140         case ADDRESS_OF:
10141             genAddrOf (ic);
10142             break;
10143             
10144         case JUMPTABLE:
10145             genJumpTab (ic);
10146             break;
10147             
10148         case CAST:
10149             genCast (ic);
10150             break;
10151             
10152         case RECEIVE:
10153             genReceive(ic);
10154             break;
10155             
10156         case SEND:
10157             addSet(&_G.sendSet,ic);
10158             break;
10159
10160         default :
10161             ic = ic;
10162         }
10163     }
10164     
10165
10166     /* now we are ready to call the 
10167        peep hole optimizer */
10168     if (!options.nopeep) {
10169       peepHole (&lineHead);
10170     }
10171     /* now do the actual printing */
10172     printLine (lineHead,codeOutFile);
10173
10174 #ifdef PCODE_DEBUG
10175     DFPRINTF((stderr,"printing pBlock\n\n"));
10176     printpBlock(stdout,pb);
10177 #endif
10178
10179     return;
10180 }