pic patches by Slade
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
29                 Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #include "common.h"
40 #include "SDCCpeeph.h"
41 #include "ralloc.h"
42 #include "pcode.h"
43 #include "gen.h"
44
45
46 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
47 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
48 void genMult8X8_8 (operand *, operand *,operand *);
49 pCode *AssembleLine(char *line);
50 extern void printpBlock(FILE *of, pBlock *pb);
51
52 static int labelOffset=0;
53 extern int debug_verbose;
54 static int optimized_for_speed = 0;
55
56 /* max_key keeps track of the largest label number used in 
57    a function. This is then used to adjust the label offset
58    for the next function.
59 */
60 static int max_key=0;
61 static int GpsuedoStkPtr=0;
62
63 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
64 unsigned int pic14aopLiteral (value *val, int offset);
65 const char *AopType(short type);
66 static iCode *ifxForOp ( operand *op, iCode *ic );
67
68 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
69
70 /* this is the down and dirty file with all kinds of 
71    kludgy & hacky stuff. This is what it is all about
72    CODE GENERATION for a specific MCU . some of the
73    routines may be reusable, will have to see */
74
75 static char *zero = "#0x00";
76 static char *one  = "#0x01";
77 static char *spname = "sp";
78
79 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
80 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
81 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
82 static char **fReturn = fReturnpic14;
83
84 static char *accUse[] = {"a","b"};
85
86 //static short rbank = -1;
87
88 static struct {
89     short r0Pushed;
90     short r1Pushed;
91     short accInUse;
92     short inLine;
93     short debugLine;
94     short nRegsSaved;
95     set *sendSet;
96 } _G;
97
98 /* Resolved ifx structure. This structure stores information
99    about an iCode ifx that makes it easier to generate code.
100 */
101 typedef struct resolvedIfx {
102   symbol *lbl;     /* pointer to a label */
103   int condition;   /* true or false ifx */
104   int generated;   /* set true when the code associated with the ifx
105                     * is generated */
106 } resolvedIfx;
107
108 extern int pic14_ptrRegReq ;
109 extern int pic14_nRegs;
110 extern FILE *codeOutFile;
111 static void saverbank (int, iCode *,bool);
112
113 static lineNode *lineHead = NULL;
114 static lineNode *lineCurr = NULL;
115
116 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
117 0xE0, 0xC0, 0x80, 0x00};
118 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
119 0x07, 0x03, 0x01, 0x00};
120
121 static  pBlock *pb;
122
123 /*-----------------------------------------------------------------*/
124 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
125 /*                 exponent of 2 is returned, otherwise -1 is      */
126 /*                 returned.                                       */
127 /* note that this is similar to the function `powof2' in SDCCsymt  */
128 /* if(n == 2^y)                                                    */
129 /*   return y;                                                     */
130 /* return -1;                                                      */
131 /*-----------------------------------------------------------------*/
132 static int my_powof2 (unsigned long num)
133 {
134   if(num) {
135     if( (num & (num-1)) == 0) {
136       int nshifts = -1;
137       while(num) {
138         num>>=1;
139         nshifts++;
140       }
141       return nshifts;
142     }
143   }
144
145   return -1;
146 }
147
148 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
149 {
150
151   DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
152                        line_no,
153                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
154                        ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
155                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
156                        ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
157                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
158                        ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
159                        ((result) ? AOP_SIZE(result) : 0));
160
161 }
162
163 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
164 {
165
166   DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
167                        line_no,
168                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
169                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
170                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
171                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
172                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
173                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
174
175 }
176
177 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
178 {
179     va_list ap;
180     char lb[INITIAL_INLINEASM];  
181     char *lbp = lb;
182
183     if(!debug_verbose)
184       return;
185
186     va_start(ap,fmt);   
187
188     if (inst && *inst) {
189         if (fmt && *fmt)
190             sprintf(lb,"%s\t",inst);
191         else
192             sprintf(lb,"%s",inst);
193         vsprintf(lb+(strlen(lb)),fmt,ap);
194     }  else
195         vsprintf(lb,fmt,ap);
196
197     while (isspace(*lbp)) lbp++;
198
199     if (lbp && *lbp) 
200         lineCurr = (lineCurr ?
201                     connectLine(lineCurr,newLineNode(lb)) :
202                     (lineHead = newLineNode(lb)));
203     lineCurr->isInline = _G.inLine;
204     lineCurr->isDebug  = _G.debugLine;
205
206     addpCode2pBlock(pb,newpCodeCharP(lb));
207
208     va_end(ap);
209 }
210
211
212 void emitpLabel(int key)
213 {
214   addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
215 }
216
217 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
218 {
219   if(pcop)
220     addpCode2pBlock(pb,newpCode(poc,pcop));
221   else
222     DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
223 }
224
225 void emitpcodeNULLop(PIC_OPCODE poc)
226 {
227
228   addpCode2pBlock(pb,newpCode(poc,NULL));
229
230 }
231
232 void emitpcodePagesel(const char *label)
233 {
234
235   char code[81];
236   strcpy(code,"\tpagesel ");
237   strcat(code,label);
238   addpCode2pBlock(pb,newpCodeInlineP(code));
239
240 }
241
242 /*-----------------------------------------------------------------*/
243 /* pic14_emitcode - writes the code into a file : for now it is simple    */
244 /*-----------------------------------------------------------------*/
245 void pic14_emitcode (char *inst,char *fmt, ...)
246 {
247     va_list ap;
248     char lb[INITIAL_INLINEASM];  
249     char *lbp = lb;
250
251     va_start(ap,fmt);   
252
253     if (inst && *inst) {
254         if (fmt && *fmt)
255             sprintf(lb,"%s\t",inst);
256         else
257             sprintf(lb,"%s",inst);
258         vsprintf(lb+(strlen(lb)),fmt,ap);
259     }  else
260         vsprintf(lb,fmt,ap);
261
262     while (isspace(*lbp)) lbp++;
263
264     if (lbp && *lbp) 
265         lineCurr = (lineCurr ?
266                     connectLine(lineCurr,newLineNode(lb)) :
267                     (lineHead = newLineNode(lb)));
268     lineCurr->isInline = _G.inLine;
269     lineCurr->isDebug  = _G.debugLine;
270
271     if(debug_verbose)
272       addpCode2pBlock(pb,newpCodeCharP(lb));
273
274     va_end(ap);
275 }
276
277
278 /*-----------------------------------------------------------------*/
279 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
280 /*-----------------------------------------------------------------*/
281 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
282 {
283     bool r0iu = FALSE , r1iu = FALSE;
284     bool r0ou = FALSE , r1ou = FALSE;
285
286     /* the logic: if r0 & r1 used in the instruction
287     then we are in trouble otherwise */
288
289     /* first check if r0 & r1 are used by this
290     instruction, in which case we are in trouble */
291     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
292         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
293     {
294         goto endOfWorld;      
295     }
296
297     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
298     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
299
300     /* if no usage of r0 then return it */
301     if (!r0iu && !r0ou) {
302         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
303         (*aopp)->type = AOP_R0;
304         
305         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
306     }
307
308     /* if no usage of r1 then return it */
309     if (!r1iu && !r1ou) {
310         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
311         (*aopp)->type = AOP_R1;
312
313         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
314     }    
315
316     /* now we know they both have usage */
317     /* if r0 not used in this instruction */
318     if (!r0iu) {
319         /* push it if not already pushed */
320         if (!_G.r0Pushed) {
321           //pic14_emitcode ("push","%s",
322           //          pic14_regWithIdx(R0_IDX)->dname);
323             _G.r0Pushed++ ;
324         }
325         
326         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
327         (*aopp)->type = AOP_R0;
328
329         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
330     }
331
332     /* if r1 not used then */
333
334     if (!r1iu) {
335         /* push it if not already pushed */
336         if (!_G.r1Pushed) {
337           //pic14_emitcode ("push","%s",
338           //          pic14_regWithIdx(R1_IDX)->dname);
339             _G.r1Pushed++ ;
340         }
341         
342         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
343         (*aopp)->type = AOP_R1;
344         return pic14_regWithIdx(R1_IDX);
345     }
346
347 endOfWorld :
348     /* I said end of world but not quite end of world yet */
349     /* if this is a result then we can push it on the stack*/
350     if (result) {
351         (*aopp)->type = AOP_STK;    
352         return NULL;
353     }
354
355     /* other wise this is true end of the world */
356     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
357            "getFreePtr should never reach here");
358     exit(0);
359 }
360
361 /*-----------------------------------------------------------------*/
362 /* newAsmop - creates a new asmOp                                  */
363 /*-----------------------------------------------------------------*/
364 asmop *newAsmop (short type)
365 {
366     asmop *aop;
367
368     aop = Safe_calloc(1,sizeof(asmop));
369     aop->type = type;
370     return aop;
371 }
372
373 static void genSetDPTR(int n)
374 {
375     if (!n)
376     {
377         pic14_emitcode(";", "Select standard DPTR");
378         pic14_emitcode("mov", "dps, #0x00");
379     }
380     else
381     {
382         pic14_emitcode(";", "Select alternate DPTR");
383         pic14_emitcode("mov", "dps, #0x01");
384     }
385 }
386
387 /*-----------------------------------------------------------------*/
388 /* resolveIfx - converts an iCode ifx into a form more useful for  */
389 /*              generating code                                    */
390 /*-----------------------------------------------------------------*/
391 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
392 {
393   if(!resIfx) 
394     return;
395
396   //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
397
398   resIfx->condition = 1;    /* assume that the ifx is true */
399   resIfx->generated = 0;    /* indicate that the ifx has not been used */
400
401   if(!ifx) {
402     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
403 /*
404     DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
405                         __FUNCTION__,__LINE__,resIfx->lbl->key);
406 */
407   } else {
408     if(IC_TRUE(ifx)) {
409       resIfx->lbl = IC_TRUE(ifx);
410     } else {
411       resIfx->lbl = IC_FALSE(ifx);
412       resIfx->condition = 0;
413     }
414 /*
415     if(IC_TRUE(ifx)) 
416       DEBUGpic14_emitcode("; ***","ifx true is non-null");
417     if(IC_FALSE(ifx)) 
418       DEBUGpic14_emitcode("; ***","ifx false is non-null");
419 */
420   }
421
422   //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
423
424 }
425 /*-----------------------------------------------------------------*/
426 /* pointerCode - returns the code for a pointer type               */
427 /*-----------------------------------------------------------------*/
428 static int pointerCode (sym_link *etype)
429 {
430
431     return PTR_TYPE(SPEC_OCLS(etype));
432
433 }
434
435 /*-----------------------------------------------------------------*/
436 /* aopForSym - for a true symbol                                   */
437 /*-----------------------------------------------------------------*/
438 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
439 {
440     asmop *aop;
441     memmap *space= SPEC_OCLS(sym->etype);
442
443     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
444     /* if already has one */
445     if (sym->aop)
446         return sym->aop;
447
448     /* assign depending on the storage class */
449     /* if it is on the stack or indirectly addressable */
450     /* space we need to assign either r0 or r1 to it   */    
451     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
452         sym->aop = aop = newAsmop(0);
453         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
454         aop->size = getSize(sym->type);
455
456         /* now assign the address of the variable to 
457         the pointer register */
458         if (aop->type != AOP_STK) {
459
460             if (sym->onStack) {
461                     if ( _G.accInUse )
462                         pic14_emitcode("push","acc");
463
464                     pic14_emitcode("mov","a,_bp");
465                     pic14_emitcode("add","a,#0x%02x",
466                              ((sym->stack < 0) ?
467                               ((char)(sym->stack - _G.nRegsSaved )) :
468                               ((char)sym->stack)) & 0xff);
469                     pic14_emitcode("mov","%s,a",
470                              aop->aopu.aop_ptr->name);
471
472                     if ( _G.accInUse )
473                         pic14_emitcode("pop","acc");
474             } else
475                 pic14_emitcode("mov","%s,#%s",
476                          aop->aopu.aop_ptr->name,
477                          sym->rname);
478             aop->paged = space->paged;
479         } else
480             aop->aopu.aop_stk = sym->stack;
481         return aop;
482     }
483     
484     if (sym->onStack && options.stack10bit)
485     {
486         /* It's on the 10 bit stack, which is located in
487          * far data space.
488          */
489          
490       //DEBUGpic14_emitcode(";","%d",__LINE__);
491
492         if ( _G.accInUse )
493                 pic14_emitcode("push","acc");
494
495         pic14_emitcode("mov","a,_bp");
496         pic14_emitcode("add","a,#0x%02x",
497                  ((sym->stack < 0) ?
498                    ((char)(sym->stack - _G.nRegsSaved )) :
499                    ((char)sym->stack)) & 0xff);
500         
501         genSetDPTR(1);
502         pic14_emitcode ("mov","dpx1,#0x40");
503         pic14_emitcode ("mov","dph1,#0x00");
504         pic14_emitcode ("mov","dpl1, a");
505         genSetDPTR(0);
506         
507         if ( _G.accInUse )
508             pic14_emitcode("pop","acc");
509             
510         sym->aop = aop = newAsmop(AOP_DPTR2);
511         aop->size = getSize(sym->type); 
512         return aop;
513     }
514
515     //DEBUGpic14_emitcode(";","%d",__LINE__);
516     /* if in bit space */
517     if (IN_BITSPACE(space)) {
518         sym->aop = aop = newAsmop (AOP_CRY);
519         aop->aopu.aop_dir = sym->rname ;
520         aop->size = getSize(sym->type);
521         //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
522         return aop;
523     }
524     /* if it is in direct space */
525     if (IN_DIRSPACE(space)) {
526         sym->aop = aop = newAsmop (AOP_DIR);
527         aop->aopu.aop_dir = sym->rname ;
528         aop->size = getSize(sym->type);
529         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
530         return aop;
531     }
532
533     /* special case for a function */
534     if (IS_FUNC(sym->type)) {   
535
536       sym->aop = aop = newAsmop(AOP_PCODE);
537       aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
538       PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
539       PCOI(aop->aopu.pcop)->_function = 1;
540       PCOI(aop->aopu.pcop)->index = 0;
541       aop->size = FPTRSIZE; 
542       /*
543         sym->aop = aop = newAsmop(AOP_IMMD);    
544         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
545         strcpy(aop->aopu.aop_immd,sym->rname);
546         aop->size = FPTRSIZE; 
547       */
548         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
549         return aop;
550     }
551
552
553     /* only remaining is far space */
554     /* in which case DPTR gets the address */
555     sym->aop = aop = newAsmop(AOP_PCODE);
556
557     aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
558     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
559     PCOI(aop->aopu.pcop)->index = 0;
560
561     DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
562                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
563
564     allocDirReg (IC_LEFT(ic));
565
566     aop->size = FPTRSIZE; 
567 /*
568     DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
569     sym->aop = aop = newAsmop(AOP_DPTR);
570     pic14_emitcode ("mov","dptr,#%s", sym->rname);
571     aop->size = getSize(sym->type);
572
573     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
574 */
575
576     /* if it is in code space */
577     if (IN_CODESPACE(space))
578         aop->code = 1;
579
580     return aop;     
581 }
582
583 /*-----------------------------------------------------------------*/
584 /* aopForRemat - rematerialzes an object                           */
585 /*-----------------------------------------------------------------*/
586 static asmop *aopForRemat (operand *op) // x symbol *sym)
587 {
588   symbol *sym = OP_SYMBOL(op);
589   iCode *ic = NULL;
590   asmop *aop = newAsmop(AOP_PCODE);
591   int val = 0;
592   int offset = 0;
593
594   ic = sym->rematiCode;
595
596   DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
597   if(IS_OP_POINTER(op)) {
598     DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
599   }
600   for (;;) {
601     if (ic->op == '+') {
602       val += (int) operandLitValue(IC_RIGHT(ic));
603     } else if (ic->op == '-') {
604       val -= (int) operandLitValue(IC_RIGHT(ic));
605     } else
606       break;
607         
608     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
609   }
610
611   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
612   aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
613   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
614   PCOI(aop->aopu.pcop)->index = val;
615
616   DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
617                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
618                       val, IS_PTR_CONST(operandType(op)));
619
620   //    DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
621
622   allocDirReg (IC_LEFT(ic));
623
624   return aop;        
625 }
626
627 int aopIdx (asmop *aop, int offset)
628 {
629   if(!aop)
630     return -1;
631
632   if(aop->type !=  AOP_REG)
633     return -2;
634         
635   return aop->aopu.aop_reg[offset]->rIdx;
636
637 }
638 /*-----------------------------------------------------------------*/
639 /* regsInCommon - two operands have some registers in common       */
640 /*-----------------------------------------------------------------*/
641 static bool regsInCommon (operand *op1, operand *op2)
642 {
643     symbol *sym1, *sym2;
644     int i;
645
646     /* if they have registers in common */
647     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
648         return FALSE ;
649
650     sym1 = OP_SYMBOL(op1);
651     sym2 = OP_SYMBOL(op2);
652
653     if (sym1->nRegs == 0 || sym2->nRegs == 0)
654         return FALSE ;
655
656     for (i = 0 ; i < sym1->nRegs ; i++) {
657         int j;
658         if (!sym1->regs[i])
659             continue ;
660
661         for (j = 0 ; j < sym2->nRegs ;j++ ) {
662             if (!sym2->regs[j])
663                 continue ;
664
665             if (sym2->regs[j] == sym1->regs[i])
666                 return TRUE ;
667         }
668     }
669
670     return FALSE ;
671 }
672
673 /*-----------------------------------------------------------------*/
674 /* operandsEqu - equivalent                                        */
675 /*-----------------------------------------------------------------*/
676 static bool operandsEqu ( operand *op1, operand *op2)
677 {
678     symbol *sym1, *sym2;
679
680     /* if they not symbols */
681     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
682         return FALSE;
683
684     sym1 = OP_SYMBOL(op1);
685     sym2 = OP_SYMBOL(op2);
686
687     /* if both are itemps & one is spilt
688        and the other is not then false */
689     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
690         sym1->isspilt != sym2->isspilt )
691         return FALSE ;
692
693     /* if they are the same */
694     if (sym1 == sym2)
695         return TRUE ;
696
697     if (strcmp(sym1->rname,sym2->rname) == 0)
698         return TRUE;
699
700
701     /* if left is a tmp & right is not */
702     if (IS_ITEMP(op1)  && 
703         !IS_ITEMP(op2) &&
704         sym1->isspilt  &&
705         (sym1->usl.spillLoc == sym2))
706         return TRUE;
707
708     if (IS_ITEMP(op2)  && 
709         !IS_ITEMP(op1) &&
710         sym2->isspilt  &&
711         sym1->level > 0 &&
712         (sym2->usl.spillLoc == sym1))
713         return TRUE ;
714
715     return FALSE ;
716 }
717
718 /*-----------------------------------------------------------------*/
719 /* pic14_sameRegs - two asmops have the same registers                   */
720 /*-----------------------------------------------------------------*/
721 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
722 {
723     int i;
724
725     if (aop1 == aop2)
726         return TRUE ;
727
728     if (aop1->type != AOP_REG ||
729         aop2->type != AOP_REG )
730         return FALSE ;
731
732     if (aop1->size != aop2->size )
733         return FALSE ;
734
735     for (i = 0 ; i < aop1->size ; i++ )
736         if (aop1->aopu.aop_reg[i] !=
737             aop2->aopu.aop_reg[i] )
738             return FALSE ;
739
740     return TRUE ;
741 }
742
743 /*-----------------------------------------------------------------*/
744 /* aopOp - allocates an asmop for an operand  :                    */
745 /*-----------------------------------------------------------------*/
746 void aopOp (operand *op, iCode *ic, bool result)
747 {
748     asmop *aop;
749     symbol *sym;
750     int i;
751
752     if (!op)
753         return ;
754
755     //    DEBUGpic14_emitcode(";","%d",__LINE__);
756     /* if this a literal */
757     if (IS_OP_LITERAL(op)) {
758         op->aop = aop = newAsmop(AOP_LIT);
759         aop->aopu.aop_lit = op->operand.valOperand;
760         aop->size = getSize(operandType(op));
761         return;
762     }
763
764     {
765       sym_link *type = operandType(op);
766       if(IS_PTR_CONST(type))
767         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
768     }
769
770     /* if already has a asmop then continue */
771     if (op->aop)
772         return ;
773
774     /* if the underlying symbol has a aop */
775     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
776       DEBUGpic14_emitcode(";","%d",__LINE__);
777         op->aop = OP_SYMBOL(op)->aop;
778         return;
779     }
780
781     /* if this is a true symbol */
782     if (IS_TRUE_SYMOP(op)) {    
783       //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
784       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
785       return ;
786     }
787
788     /* this is a temporary : this has
789     only four choices :
790     a) register
791     b) spillocation
792     c) rematerialize 
793     d) conditional   
794     e) can be a return use only */
795
796     sym = OP_SYMBOL(op);
797
798
799     /* if the type is a conditional */
800     if (sym->regType == REG_CND) {
801         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
802         aop->size = 0;
803         return;
804     }
805
806     /* if it is spilt then two situations
807     a) is rematerialize 
808     b) has a spill location */
809     if (sym->isspilt || sym->nRegs == 0) {
810
811       DEBUGpic14_emitcode(";","%d",__LINE__);
812         /* rematerialize it NOW */
813         if (sym->remat) {
814
815             sym->aop = op->aop = aop =
816                                       aopForRemat (op);
817             aop->size = getSize(sym->type);
818             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
819             return;
820         }
821
822         if (sym->accuse) {
823             int i;
824             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
825             aop->size = getSize(sym->type);
826             for ( i = 0 ; i < 2 ; i++ )
827                 aop->aopu.aop_str[i] = accUse[i];
828             DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
829             return;  
830         }
831
832         if (sym->ruonly ) {
833           if(sym->isptr) {  // && sym->uptr 
834             aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
835             aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
836
837             //PCOI(aop->aopu.pcop)->_const = 0;
838             //PCOI(aop->aopu.pcop)->index = 0;
839             /*
840               DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
841               __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
842             */
843             //allocDirReg (IC_LEFT(ic));
844
845             aop->size = getSize(sym->type);
846             DEBUGpic14_emitcode(";","%d",__LINE__);
847             return;
848
849           } else {
850
851             unsigned i;
852
853             aop = op->aop = sym->aop = newAsmop(AOP_STR);
854             aop->size = getSize(sym->type);
855             for ( i = 0 ; i < fReturnSizePic ; i++ )
856               aop->aopu.aop_str[i] = fReturn[i];
857
858             DEBUGpic14_emitcode(";","%d",__LINE__);
859             return;
860           }
861         }
862
863         /* else spill location  */
864         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
865             /* force a new aop if sizes differ */
866             sym->usl.spillLoc->aop = NULL;
867         }
868         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
869                             __FUNCTION__,__LINE__,
870                             sym->usl.spillLoc->rname,
871                             sym->rname, sym->usl.spillLoc->offset);
872
873         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
874         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
875         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
876                                           getSize(sym->type), 
877                                           sym->usl.spillLoc->offset);
878         aop->size = getSize(sym->type);
879
880         return;
881     }
882
883     {
884       sym_link *type = operandType(op);
885       if(IS_PTR_CONST(type)) 
886         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
887     }
888
889     /* must be in a register */
890     DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
891     sym->aop = op->aop = aop = newAsmop(AOP_REG);
892     aop->size = sym->nRegs;
893     for ( i = 0 ; i < sym->nRegs ;i++)
894         aop->aopu.aop_reg[i] = sym->regs[i];
895 }
896
897 /*-----------------------------------------------------------------*/
898 /* freeAsmop - free up the asmop given to an operand               */
899 /*----------------------------------------------------------------*/
900 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
901 {   
902     asmop *aop ;
903
904     if (!op)
905         aop = aaop;
906     else 
907         aop = op->aop;
908
909     if (!aop)
910         return ;
911
912     if (aop->freed)
913         goto dealloc; 
914
915     aop->freed = 1;
916
917     /* depending on the asmop type only three cases need work AOP_RO
918        , AOP_R1 && AOP_STK */
919 #if 0
920     switch (aop->type) {
921         case AOP_R0 :
922             if (_G.r0Pushed ) {
923                 if (pop) {
924                     pic14_emitcode ("pop","ar0");     
925                     _G.r0Pushed--;
926                 }
927             }
928             bitVectUnSetBit(ic->rUsed,R0_IDX);
929             break;
930
931         case AOP_R1 :
932             if (_G.r1Pushed ) {
933                 if (pop) {
934                     pic14_emitcode ("pop","ar1");
935                     _G.r1Pushed--;
936                 }
937             }
938             bitVectUnSetBit(ic->rUsed,R1_IDX);          
939             break;
940
941         case AOP_STK :
942         {
943             int sz = aop->size;    
944             int stk = aop->aopu.aop_stk + aop->size;
945             bitVectUnSetBit(ic->rUsed,R0_IDX);
946             bitVectUnSetBit(ic->rUsed,R1_IDX);          
947
948             getFreePtr(ic,&aop,FALSE);
949             
950             if (options.stack10bit)
951             {
952                 /* I'm not sure what to do here yet... */
953                 /* #STUB */
954                 fprintf(stderr, 
955                         "*** Warning: probably generating bad code for "
956                         "10 bit stack mode.\n");
957             }
958             
959             if (stk) {
960                 pic14_emitcode ("mov","a,_bp");
961                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
962                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
963             } else {
964                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
965             }
966
967             while (sz--) {
968                 pic14_emitcode("pop","acc");
969                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
970                 if (!sz) break;
971                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
972             }
973             op->aop = aop;
974             freeAsmop(op,NULL,ic,TRUE);
975             if (_G.r0Pushed) {
976                 pic14_emitcode("pop","ar0");
977                 _G.r0Pushed--;
978             }
979
980             if (_G.r1Pushed) {
981                 pic14_emitcode("pop","ar1");
982                 _G.r1Pushed--;
983             }       
984         }
985     }
986 #endif
987
988 dealloc:
989     /* all other cases just dealloc */
990     if (op ) {
991         op->aop = NULL;
992         if (IS_SYMOP(op)) {
993             OP_SYMBOL(op)->aop = NULL;    
994             /* if the symbol has a spill */
995             if (SPIL_LOC(op))
996                 SPIL_LOC(op)->aop = NULL;
997         }
998     }
999 }
1000
1001 /*-----------------------------------------------------------------*/
1002 /* aopGet - for fetching value of the aop                          */
1003 /*-----------------------------------------------------------------*/
1004 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1005 {
1006     char *s = buffer ;
1007     char *rs;
1008
1009     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1010     /* offset is greater than
1011     size then zero */
1012     if (offset > (aop->size - 1) &&
1013         aop->type != AOP_LIT)
1014         return zero;
1015
1016     /* depending on type */
1017     switch (aop->type) {
1018         
1019     case AOP_R0:
1020     case AOP_R1:
1021         DEBUGpic14_emitcode(";","%d",__LINE__);
1022         /* if we need to increment it */       
1023         while (offset > aop->coff) {        
1024             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1025             aop->coff++;
1026         }
1027         
1028         while (offset < aop->coff) {
1029             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1030             aop->coff--;
1031         }
1032         
1033         aop->coff = offset ;
1034         if (aop->paged) {
1035             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1036             return (dname ? "acc" : "a");
1037         }       
1038         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1039         rs = Safe_calloc(1,strlen(s)+1);
1040         strcpy(rs,s);   
1041         return rs;
1042         
1043     case AOP_DPTR:
1044     case AOP_DPTR2:
1045         DEBUGpic14_emitcode(";","%d",__LINE__);
1046     if (aop->type == AOP_DPTR2)
1047     {
1048         genSetDPTR(1);
1049     }
1050     
1051         while (offset > aop->coff) {
1052             pic14_emitcode ("inc","dptr");
1053             aop->coff++;
1054         }
1055         
1056         while (offset < aop->coff) {        
1057             pic14_emitcode("lcall","__decdptr");
1058             aop->coff--;
1059         }
1060         
1061         aop->coff = offset;
1062         if (aop->code) {
1063             pic14_emitcode("clr","a");
1064             pic14_emitcode("movc","a,@a+dptr");
1065         }
1066     else {
1067             pic14_emitcode("movx","a,@dptr");
1068     }
1069             
1070     if (aop->type == AOP_DPTR2)
1071     {
1072         genSetDPTR(0);
1073     }
1074             
1075     return (dname ? "acc" : "a");
1076         
1077         
1078     case AOP_IMMD:
1079         if (bit16) 
1080             sprintf (s,"%s",aop->aopu.aop_immd);
1081         else
1082             if (offset) 
1083                 sprintf(s,"(%s >> %d)",
1084                         aop->aopu.aop_immd,
1085                         offset*8);
1086             else
1087                 sprintf(s,"%s",
1088                         aop->aopu.aop_immd);
1089         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1090         rs = Safe_calloc(1,strlen(s)+1);
1091         strcpy(rs,s);   
1092         return rs;
1093         
1094     case AOP_DIR:
1095       if (offset) {
1096         sprintf(s,"(%s + %d)",
1097                 aop->aopu.aop_dir,
1098                 offset);
1099         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1100       } else
1101             sprintf(s,"%s",aop->aopu.aop_dir);
1102         rs = Safe_calloc(1,strlen(s)+1);
1103         strcpy(rs,s);   
1104         return rs;
1105         
1106     case AOP_REG:
1107       //if (dname) 
1108       //    return aop->aopu.aop_reg[offset]->dname;
1109       //else
1110             return aop->aopu.aop_reg[offset]->name;
1111         
1112     case AOP_CRY:
1113       //pic14_emitcode(";","%d",__LINE__);
1114       return aop->aopu.aop_dir;
1115         
1116     case AOP_ACC:
1117         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1118         return "AOP_accumulator_bug";
1119
1120     case AOP_LIT:
1121         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1122         rs = Safe_calloc(1,strlen(s)+1);
1123         strcpy(rs,s);   
1124         return rs;
1125         
1126     case AOP_STR:
1127         aop->coff = offset ;
1128         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1129             dname)
1130             return "acc";
1131         DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1132         
1133         return aop->aopu.aop_str[offset];
1134         
1135     case AOP_PCODE:
1136       {
1137         pCodeOp *pcop = aop->aopu.pcop;
1138         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1139         if(pcop->name) {
1140           DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1141           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1142           sprintf(s,"%s", pcop->name);
1143         } else
1144           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1145
1146       }
1147       rs = Safe_calloc(1,strlen(s)+1);
1148       strcpy(rs,s);   
1149       return rs;
1150
1151     }
1152
1153     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1154            "aopget got unsupported aop->type");
1155     exit(0);
1156 }
1157
1158
1159 /*-----------------------------------------------------------------*/
1160 /* popGetTempReg - create a new temporary pCodeOp                  */
1161 /*-----------------------------------------------------------------*/
1162 pCodeOp *popGetTempReg(void)
1163 {
1164
1165   pCodeOp *pcop;
1166
1167   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1168   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1169     PCOR(pcop)->r->wasUsed=1;
1170     PCOR(pcop)->r->isFree=0;
1171   }
1172
1173   return pcop;
1174 }
1175
1176 /*-----------------------------------------------------------------*/
1177 /* popGetTempReg - create a new temporary pCodeOp                  */
1178 /*-----------------------------------------------------------------*/
1179 void popReleaseTempReg(pCodeOp *pcop)
1180 {
1181
1182   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1183     PCOR(pcop)->r->isFree = 1;
1184
1185 }
1186 /*-----------------------------------------------------------------*/
1187 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1188 /*-----------------------------------------------------------------*/
1189 pCodeOp *popGetLabel(unsigned int key)
1190 {
1191
1192   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1193
1194   if(key>(unsigned int)max_key)
1195     max_key = key;
1196
1197   return newpCodeOpLabel(NULL,key+100+labelOffset);
1198 }
1199
1200 /*-------------------------------------------------------------------*/
1201 /* popGetLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1202 /*-------------------------------------------------------------------*/
1203 pCodeOp *popGetHighLabel(unsigned int key)
1204 {
1205   pCodeOp *pcop;
1206   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1207
1208   if(key>(unsigned int)max_key)
1209     max_key = key;
1210
1211   pcop = newpCodeOpLabel(NULL,key+100+labelOffset);
1212   PCOLAB(pcop)->offset = 1;
1213   return pcop;
1214 }
1215
1216 /*-----------------------------------------------------------------*/
1217 /* popCopyReg - copy a pcode operator                              */
1218 /*-----------------------------------------------------------------*/
1219 pCodeOp *popCopyReg(pCodeOpReg *pc)
1220 {
1221   pCodeOpReg *pcor;
1222
1223   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1224   pcor->pcop.type = pc->pcop.type;
1225   if(pc->pcop.name) {
1226     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1227       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1228   } else
1229     pcor->pcop.name = NULL;
1230
1231   pcor->r = pc->r;
1232   pcor->rIdx = pc->rIdx;
1233   pcor->r->wasUsed=1;
1234
1235   //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1236
1237   return PCOP(pcor);
1238 }
1239 /*-----------------------------------------------------------------*/
1240 /* popGet - asm operator to pcode operator conversion              */
1241 /*-----------------------------------------------------------------*/
1242 pCodeOp *popGetLit(unsigned int lit)
1243 {
1244
1245   return newpCodeOpLit(lit);
1246 }
1247
1248
1249 /*-----------------------------------------------------------------*/
1250 /* popGetImmd - asm operator to pcode immediate conversion         */
1251 /*-----------------------------------------------------------------*/
1252 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1253 {
1254
1255   return newpCodeOpImmd(name, offset,index, 0, is_func);
1256 }
1257
1258
1259 /*-----------------------------------------------------------------*/
1260 /* popGet - asm operator to pcode operator conversion              */
1261 /*-----------------------------------------------------------------*/
1262 pCodeOp *popGetWithString(char *str)
1263 {
1264   pCodeOp *pcop;
1265
1266
1267   if(!str) {
1268     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1269     exit (1);
1270   }
1271
1272   pcop = newpCodeOp(str,PO_STR);
1273
1274   return pcop;
1275 }
1276
1277 /*-----------------------------------------------------------------*/
1278 /* popRegFromString -                                              */
1279 /*-----------------------------------------------------------------*/
1280 pCodeOp *popRegFromString(char *str, int size, int offset)
1281 {
1282
1283   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1284   pcop->type = PO_DIR;
1285
1286   DEBUGpic14_emitcode(";","%d",__LINE__);
1287
1288   if(!str)
1289     str = "BAD_STRING";
1290
1291   pcop->name = Safe_calloc(1,strlen(str)+1);
1292   strcpy(pcop->name,str);
1293
1294   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1295
1296   PCOR(pcop)->r = dirregWithName(pcop->name);
1297   if(PCOR(pcop)->r == NULL) {
1298     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1299     PCOR(pcop)->r = allocRegByName (pcop->name,size);
1300     DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1301   } else {
1302     DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1303   }
1304   PCOR(pcop)->instance = offset;
1305
1306   return pcop;
1307 }
1308
1309 pCodeOp *popRegFromIdx(int rIdx)
1310 {
1311   pCodeOp *pcop;
1312
1313   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1314                        __FUNCTION__,__LINE__,rIdx);
1315
1316   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1317
1318   PCOR(pcop)->rIdx = rIdx;
1319   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1320   PCOR(pcop)->r->isFree = 0;
1321   PCOR(pcop)->r->wasUsed = 1;
1322
1323   pcop->type = PCOR(pcop)->r->pc_type;
1324
1325
1326   return pcop;
1327 }
1328 /*-----------------------------------------------------------------*/
1329 /* popGet - asm operator to pcode operator conversion              */
1330 /*-----------------------------------------------------------------*/
1331 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1332 {
1333   //char *s = buffer ;
1334     //char *rs;
1335
1336     pCodeOp *pcop;
1337
1338     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1339     /* offset is greater than
1340     size then zero */
1341
1342     if (offset > (aop->size - 1) &&
1343         aop->type != AOP_LIT)
1344       return NULL;  //zero;
1345
1346     /* depending on type */
1347     switch (aop->type) {
1348         
1349     case AOP_R0:
1350     case AOP_R1:
1351     case AOP_DPTR:
1352     case AOP_DPTR2:
1353     case AOP_ACC:
1354         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1355         return NULL;
1356         
1357     case AOP_IMMD:
1358       DEBUGpic14_emitcode(";","%d",__LINE__);
1359       return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1360
1361     case AOP_DIR:
1362       return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1363 #if 0
1364         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1365         pcop->type = PO_DIR;
1366
1367         /*
1368         if (offset)
1369             sprintf(s,"(%s + %d)",
1370                     aop->aopu.aop_dir,
1371                     offset);
1372         else
1373             sprintf(s,"%s",aop->aopu.aop_dir);
1374         pcop->name = Safe_calloc(1,strlen(s)+1);
1375         strcpy(pcop->name,s);   
1376         */
1377         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1378         strcpy(pcop->name,aop->aopu.aop_dir);   
1379         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1380         if(PCOR(pcop)->r == NULL) {
1381           //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1382           PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1383           DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1384         } else {
1385           DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1386         }
1387         PCOR(pcop)->instance = offset;
1388
1389         return pcop;
1390 #endif
1391         
1392     case AOP_REG:
1393       {
1394         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1395
1396         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1397         PCOR(pcop)->rIdx = rIdx;
1398         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1399         PCOR(pcop)->r->wasUsed=1;
1400         PCOR(pcop)->r->isFree=0;
1401
1402         PCOR(pcop)->instance = offset;
1403         pcop->type = PCOR(pcop)->r->pc_type;
1404         //rs = aop->aopu.aop_reg[offset]->name;
1405         DEBUGpic14_emitcode(";","%d regiser idx = %d ",__LINE__,rIdx);
1406         return pcop;
1407       }
1408
1409     case AOP_CRY:
1410       pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1411       PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1412       //if(PCOR(pcop)->r == NULL)
1413       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1414       return pcop;
1415         
1416     case AOP_LIT:
1417       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1418
1419     case AOP_STR:
1420       DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1421       return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1422       /*
1423       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1424       PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1425       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1426       pcop->type = PCOR(pcop)->r->pc_type;
1427       pcop->name = PCOR(pcop)->r->name;
1428
1429       return pcop;
1430       */
1431
1432     case AOP_PCODE:
1433       DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s) %d %s",pCodeOpType(aop->aopu.pcop),
1434                           __LINE__, 
1435                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1436       pcop = pCodeOpCopy(aop->aopu.pcop);
1437       PCOI(pcop)->offset = offset;
1438       return pcop;
1439     }
1440
1441     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1442            "popGet got unsupported aop->type");
1443     exit(0);
1444 }
1445 /*-----------------------------------------------------------------*/
1446 /* aopPut - puts a string for a aop                                */
1447 /*-----------------------------------------------------------------*/
1448 void aopPut (asmop *aop, char *s, int offset)
1449 {
1450     char *d = buffer ;
1451     symbol *lbl ;
1452
1453     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1454
1455     if (aop->size && offset > ( aop->size - 1)) {
1456         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1457                "aopPut got offset > aop->size");
1458         exit(0);
1459     }
1460
1461     /* will assign value to value */
1462     /* depending on where it is ofcourse */
1463     switch (aop->type) {
1464     case AOP_DIR:
1465       if (offset) {
1466         sprintf(d,"(%s + %d)",
1467                 aop->aopu.aop_dir,offset);
1468         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1469
1470       } else
1471             sprintf(d,"%s",aop->aopu.aop_dir);
1472         
1473         if (strcmp(d,s)) {
1474           DEBUGpic14_emitcode(";","%d",__LINE__);
1475           if(strcmp(s,"W"))
1476             pic14_emitcode("movf","%s,w",s);
1477           pic14_emitcode("movwf","%s",d);
1478
1479           if(strcmp(s,"W")) {
1480             pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1481             if(offset >= aop->size) {
1482               emitpcode(POC_CLRF,popGet(aop,offset));
1483               break;
1484             } else
1485               emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1486           }
1487
1488           emitpcode(POC_MOVWF,popGet(aop,offset));
1489
1490
1491         }
1492         break;
1493         
1494     case AOP_REG:
1495       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1496         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1497           /*
1498             if (*s == '@'           ||
1499                 strcmp(s,"r0") == 0 ||
1500                 strcmp(s,"r1") == 0 ||
1501                 strcmp(s,"r2") == 0 ||
1502                 strcmp(s,"r3") == 0 ||
1503                 strcmp(s,"r4") == 0 ||
1504                 strcmp(s,"r5") == 0 ||
1505                 strcmp(s,"r6") == 0 || 
1506                 strcmp(s,"r7") == 0 )
1507                 pic14_emitcode("mov","%s,%s  ; %d",
1508                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1509             else
1510           */
1511
1512           if(strcmp(s,"W")==0 )
1513             pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1514
1515           pic14_emitcode("movwf","%s",
1516                    aop->aopu.aop_reg[offset]->name);
1517
1518           if(strcmp(s,zero)==0) {
1519             emitpcode(POC_CLRF,popGet(aop,offset));
1520
1521           } else if(strcmp(s,"W")==0) {
1522             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1523             pcop->type = PO_GPR_REGISTER;
1524
1525             PCOR(pcop)->rIdx = -1;
1526             PCOR(pcop)->r = NULL;
1527
1528             DEBUGpic14_emitcode(";","%d",__LINE__);
1529             pcop->name = Safe_strdup(s);
1530             emitpcode(POC_MOVFW,pcop);
1531             emitpcode(POC_MOVWF,popGet(aop,offset));
1532           } else if(strcmp(s,one)==0) {
1533             emitpcode(POC_CLRF,popGet(aop,offset));
1534             emitpcode(POC_INCF,popGet(aop,offset));
1535           } else {
1536             emitpcode(POC_MOVWF,popGet(aop,offset));
1537           }
1538         }
1539         break;
1540         
1541     case AOP_DPTR:
1542     case AOP_DPTR2:
1543     
1544     if (aop->type == AOP_DPTR2)
1545     {
1546         genSetDPTR(1);
1547     }
1548     
1549         if (aop->code) {
1550             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1551                    "aopPut writting to code space");
1552             exit(0);
1553         }
1554         
1555         while (offset > aop->coff) {
1556             aop->coff++;
1557             pic14_emitcode ("inc","dptr");
1558         }
1559         
1560         while (offset < aop->coff) {
1561             aop->coff-- ;
1562             pic14_emitcode("lcall","__decdptr");
1563         }
1564         
1565         aop->coff = offset;
1566         
1567         /* if not in accumulater */
1568         MOVA(s);        
1569         
1570         pic14_emitcode ("movx","@dptr,a");
1571         
1572     if (aop->type == AOP_DPTR2)
1573     {
1574         genSetDPTR(0);
1575     }
1576         break;
1577         
1578     case AOP_R0:
1579     case AOP_R1:
1580         while (offset > aop->coff) {
1581             aop->coff++;
1582             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1583         }
1584         while (offset < aop->coff) {
1585             aop->coff-- ;
1586             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1587         }
1588         aop->coff = offset;
1589         
1590         if (aop->paged) {
1591             MOVA(s);           
1592             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1593             
1594         } else
1595             if (*s == '@') {
1596                 MOVA(s);
1597                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1598             } else
1599                 if (strcmp(s,"r0") == 0 ||
1600                     strcmp(s,"r1") == 0 ||
1601                     strcmp(s,"r2") == 0 ||
1602                     strcmp(s,"r3") == 0 ||
1603                     strcmp(s,"r4") == 0 ||
1604                     strcmp(s,"r5") == 0 ||
1605                     strcmp(s,"r6") == 0 || 
1606                     strcmp(s,"r7") == 0 ) {
1607                     char buffer[10];
1608                     sprintf(buffer,"a%s",s);
1609                     pic14_emitcode("mov","@%s,%s",
1610                              aop->aopu.aop_ptr->name,buffer);
1611                 } else
1612                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1613         
1614         break;
1615         
1616     case AOP_STK:
1617         if (strcmp(s,"a") == 0)
1618             pic14_emitcode("push","acc");
1619         else
1620             pic14_emitcode("push","%s",s);
1621         
1622         break;
1623         
1624     case AOP_CRY:
1625         /* if bit variable */
1626         if (!aop->aopu.aop_dir) {
1627             pic14_emitcode("clr","a");
1628             pic14_emitcode("rlc","a");
1629         } else {
1630             if (s == zero) 
1631                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1632             else
1633                 if (s == one)
1634                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1635                 else
1636                     if (!strcmp(s,"c"))
1637                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1638                     else {
1639                         lbl = newiTempLabel(NULL);
1640                         
1641                         if (strcmp(s,"a")) {
1642                             MOVA(s);
1643                         }
1644                         pic14_emitcode("clr","c");
1645                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1646                         pic14_emitcode("cpl","c");
1647                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1648                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1649                     }
1650         }
1651         break;
1652         
1653     case AOP_STR:
1654         aop->coff = offset;
1655         if (strcmp(aop->aopu.aop_str[offset],s))
1656             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1657         break;
1658         
1659     case AOP_ACC:
1660         aop->coff = offset;
1661         if (!offset && (strcmp(s,"acc") == 0))
1662             break;
1663         
1664         if (strcmp(aop->aopu.aop_str[offset],s))
1665             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1666         break;
1667
1668     default :
1669         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1670                "aopPut got unsupported aop->type");
1671         exit(0);    
1672     }    
1673
1674 }
1675
1676 /*-----------------------------------------------------------------*/
1677 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1678 /*-----------------------------------------------------------------*/
1679 void mov2w (asmop *aop, int offset)
1680 {
1681
1682   if(!aop)
1683     return;
1684
1685   DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1686
1687   if ( aop->type == AOP_PCODE ||
1688        aop->type == AOP_LIT ||
1689        aop->type == AOP_IMMD )
1690     emitpcode(POC_MOVLW,popGet(aop,offset));
1691   else
1692     emitpcode(POC_MOVFW,popGet(aop,offset));
1693
1694 }
1695
1696 /*-----------------------------------------------------------------*/
1697 /* reAdjustPreg - points a register back to where it should        */
1698 /*-----------------------------------------------------------------*/
1699 static void reAdjustPreg (asmop *aop)
1700 {
1701     int size ;
1702
1703     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1704     aop->coff = 0;
1705     if ((size = aop->size) <= 1)
1706         return ;
1707     size-- ;
1708     switch (aop->type) {
1709         case AOP_R0 :
1710         case AOP_R1 :
1711             while (size--)
1712                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1713             break;          
1714         case AOP_DPTR :
1715         case AOP_DPTR2:
1716             if (aop->type == AOP_DPTR2)
1717             {
1718                 genSetDPTR(1);
1719             } 
1720             while (size--)
1721             {
1722                 pic14_emitcode("lcall","__decdptr");
1723             }
1724                 
1725             if (aop->type == AOP_DPTR2)
1726             {
1727                 genSetDPTR(0);
1728             }                
1729             break;  
1730
1731     }   
1732
1733 }
1734
1735 /*-----------------------------------------------------------------*/
1736 /* genNotFloat - generates not for float operations              */
1737 /*-----------------------------------------------------------------*/
1738 static void genNotFloat (operand *op, operand *res)
1739 {
1740     int size, offset;
1741     char *l;
1742     symbol *tlbl ;
1743
1744     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1745     /* we will put 127 in the first byte of 
1746     the result */
1747     aopPut(AOP(res),"#127",0);
1748     size = AOP_SIZE(op) - 1;
1749     offset = 1;
1750
1751     l = aopGet(op->aop,offset++,FALSE,FALSE);
1752     MOVA(l);    
1753
1754     while(size--) {
1755         pic14_emitcode("orl","a,%s",
1756                  aopGet(op->aop,
1757                         offset++,FALSE,FALSE));
1758     }
1759     tlbl = newiTempLabel(NULL);
1760
1761     tlbl = newiTempLabel(NULL);
1762     aopPut(res->aop,one,1);
1763     pic14_emitcode("jz","%05d_DS_",(tlbl->key+100));
1764     aopPut(res->aop,zero,1);
1765     pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
1766
1767     size = res->aop->size - 2;
1768     offset = 2;    
1769     /* put zeros in the rest */
1770     while (size--) 
1771         aopPut(res->aop,zero,offset++);
1772 }
1773
1774 #if 0
1775 /*-----------------------------------------------------------------*/
1776 /* opIsGptr: returns non-zero if the passed operand is             */   
1777 /* a generic pointer type.                                         */
1778 /*-----------------------------------------------------------------*/ 
1779 static int opIsGptr(operand *op)
1780 {
1781     sym_link *type = operandType(op);
1782     
1783     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1784     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1785     {
1786         return 1;
1787     }
1788     return 0;        
1789 }
1790 #endif
1791
1792 /*-----------------------------------------------------------------*/
1793 /* pic14_getDataSize - get the operand data size                         */
1794 /*-----------------------------------------------------------------*/
1795 int pic14_getDataSize(operand *op)
1796 {
1797     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1798
1799
1800     return AOP_SIZE(op);
1801
1802     // tsd- in the pic port, the genptr size is 1, so this code here
1803     // fails. ( in the 8051 port, the size was 4).
1804 #if 0
1805     int size;
1806     size = AOP_SIZE(op);
1807     if (size == GPTRSIZE)
1808     {
1809         sym_link *type = operandType(op);
1810         if (IS_GENPTR(type))
1811         {
1812             /* generic pointer; arithmetic operations
1813              * should ignore the high byte (pointer type).
1814              */
1815             size--;
1816     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1817         }
1818     }
1819     return size;
1820 #endif
1821 }
1822
1823 /*-----------------------------------------------------------------*/
1824 /* pic14_outAcc - output Acc                                             */
1825 /*-----------------------------------------------------------------*/
1826 void pic14_outAcc(operand *result)
1827 {
1828   int size,offset;
1829   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1830   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1831
1832
1833   size = pic14_getDataSize(result);
1834   if(size){
1835     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1836     size--;
1837     offset = 1;
1838     /* unsigned or positive */
1839     while(size--)
1840       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1841   }
1842
1843 }
1844
1845 /*-----------------------------------------------------------------*/
1846 /* pic14_outBitC - output a bit C                                        */
1847 /*-----------------------------------------------------------------*/
1848 void pic14_outBitC(operand *result)
1849 {
1850
1851     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1852     /* if the result is bit */
1853     if (AOP_TYPE(result) == AOP_CRY) 
1854         aopPut(AOP(result),"c",0);
1855     else {
1856         pic14_emitcode("clr","a  ; %d", __LINE__);
1857         pic14_emitcode("rlc","a");
1858         pic14_outAcc(result);
1859     }
1860 }
1861
1862 /*-----------------------------------------------------------------*/
1863 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1864 /*-----------------------------------------------------------------*/
1865 void pic14_toBoolean(operand *oper)
1866 {
1867     int size = AOP_SIZE(oper) - 1;
1868     int offset = 1;
1869
1870     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1871
1872     if ( AOP_TYPE(oper) != AOP_ACC) {
1873       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1874     }
1875     while (size--) {
1876       emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1877     }
1878 }
1879
1880
1881 /*-----------------------------------------------------------------*/
1882 /* genNot - generate code for ! operation                          */
1883 /*-----------------------------------------------------------------*/
1884 static void genNot (iCode *ic)
1885 {
1886   symbol *tlbl;
1887   sym_link *optype = operandType(IC_LEFT(ic));
1888   int size;
1889
1890   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1891   /* assign asmOps to operand & result */
1892   aopOp (IC_LEFT(ic),ic,FALSE);
1893   aopOp (IC_RESULT(ic),ic,TRUE);
1894
1895   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1896   /* if in bit space then a special case */
1897   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1898     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1899       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1900       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1901     } else {
1902       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1903       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1904       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1905     }
1906     goto release;
1907   }
1908
1909   /* if type float then do float */
1910   if (IS_FLOAT(optype)) {
1911     genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1912     goto release;
1913   }
1914
1915   size = AOP_SIZE(IC_RESULT(ic));
1916   if(size == 1) {
1917     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1918     emitpcode(POC_ANDLW,popGetLit(1));
1919     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1920     goto release;
1921   }
1922   pic14_toBoolean(IC_LEFT(ic));
1923
1924   tlbl = newiTempLabel(NULL);
1925   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1926   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1927   pic14_outBitC(IC_RESULT(ic));
1928
1929  release:    
1930   /* release the aops */
1931   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1932   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1933 }
1934
1935
1936 /*-----------------------------------------------------------------*/
1937 /* genCpl - generate code for complement                           */
1938 /*-----------------------------------------------------------------*/
1939 static void genCpl (iCode *ic)
1940 {
1941   operand *left, *result;
1942   int size, offset=0;  
1943
1944
1945   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1946   aopOp((left = IC_LEFT(ic)),ic,FALSE);
1947   aopOp((result=IC_RESULT(ic)),ic,TRUE);
1948
1949   /* if both are in bit space then 
1950      a special case */
1951   if (AOP_TYPE(result) == AOP_CRY &&
1952       AOP_TYPE(left) == AOP_CRY ) { 
1953
1954     pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1955     pic14_emitcode("cpl","c"); 
1956     pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1957     goto release; 
1958   } 
1959
1960   size = AOP_SIZE(result);
1961   while (size--) {
1962
1963     if(AOP_TYPE(left) == AOP_ACC) 
1964       emitpcode(POC_XORLW, popGetLit(0xff));
1965     else
1966       emitpcode(POC_COMFW,popGet(AOP(left),offset));
1967
1968     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1969
1970   }
1971
1972
1973 release:
1974     /* release the aops */
1975     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1976     freeAsmop(result,NULL,ic,TRUE);
1977 }
1978
1979 /*-----------------------------------------------------------------*/
1980 /* genUminusFloat - unary minus for floating points                */
1981 /*-----------------------------------------------------------------*/
1982 static void genUminusFloat(operand *op,operand *result)
1983 {
1984     int size ,offset =0 ;
1985     char *l;
1986
1987     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1988     /* for this we just need to flip the 
1989     first it then copy the rest in place */
1990     size = AOP_SIZE(op) - 1;
1991     l = aopGet(AOP(op),3,FALSE,FALSE);
1992
1993     MOVA(l);    
1994
1995     pic14_emitcode("cpl","acc.7");
1996     aopPut(AOP(result),"a",3);    
1997
1998     while(size--) {
1999         aopPut(AOP(result),
2000                aopGet(AOP(op),offset,FALSE,FALSE),
2001                offset);
2002         offset++;
2003     }          
2004 }
2005
2006 /*-----------------------------------------------------------------*/
2007 /* genUminus - unary minus code generation                         */
2008 /*-----------------------------------------------------------------*/
2009 static void genUminus (iCode *ic)
2010 {
2011   int size, i;
2012   sym_link *optype, *rtype;
2013
2014
2015   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2016   /* assign asmops */
2017   aopOp(IC_LEFT(ic),ic,FALSE);
2018   aopOp(IC_RESULT(ic),ic,TRUE);
2019
2020   /* if both in bit space then special
2021      case */
2022   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2023       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2024
2025     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
2026     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2027     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
2028
2029     goto release; 
2030   } 
2031
2032   optype = operandType(IC_LEFT(ic));
2033   rtype = operandType(IC_RESULT(ic));
2034
2035   /* if float then do float stuff */
2036   if (IS_FLOAT(optype)) {
2037     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2038     goto release;
2039   }
2040
2041   /* otherwise subtract from zero by taking the 2's complement */
2042   size = AOP_SIZE(IC_LEFT(ic));
2043
2044   for(i=0; i<size; i++) {
2045     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2046       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2047     else {
2048       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2049       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2050     }
2051   }
2052
2053   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2054   for(i=1; i<size; i++) {
2055     emitSKPNZ;
2056     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2057   }
2058
2059  release:
2060   /* release the aops */
2061   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2062   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2063 }
2064
2065 /*-----------------------------------------------------------------*/
2066 /* saveRegisters - will look for a call and save the registers     */
2067 /*-----------------------------------------------------------------*/
2068 static void saveRegisters(iCode *lic) 
2069 {
2070     int i;
2071     iCode *ic;
2072     bitVect *rsave;
2073     sym_link *dtype;
2074
2075     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2076     /* look for call */
2077     for (ic = lic ; ic ; ic = ic->next) 
2078         if (ic->op == CALL || ic->op == PCALL)
2079             break;
2080
2081     if (!ic) {
2082         fprintf(stderr,"found parameter push with no function call\n");
2083         return ;
2084     }
2085
2086     /* if the registers have been saved already then
2087     do nothing */
2088     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2089         return ;
2090
2091     /* find the registers in use at this time 
2092     and push them away to safety */
2093     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2094                           ic->rUsed);
2095
2096     ic->regsSaved = 1;
2097     if (options.useXstack) {
2098         if (bitVectBitValue(rsave,R0_IDX))
2099             pic14_emitcode("mov","b,r0");
2100         pic14_emitcode("mov","r0,%s",spname);
2101         for (i = 0 ; i < pic14_nRegs ; i++) {
2102             if (bitVectBitValue(rsave,i)) {
2103                 if (i == R0_IDX)
2104                     pic14_emitcode("mov","a,b");
2105                 else
2106                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2107                 pic14_emitcode("movx","@r0,a");
2108                 pic14_emitcode("inc","r0");
2109             }
2110         }
2111         pic14_emitcode("mov","%s,r0",spname);
2112         if (bitVectBitValue(rsave,R0_IDX))
2113             pic14_emitcode("mov","r0,b");           
2114     }// else
2115     //for (i = 0 ; i < pic14_nRegs ; i++) {
2116     //    if (bitVectBitValue(rsave,i))
2117     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2118     //}
2119
2120     dtype = operandType(IC_LEFT(ic));
2121     if (currFunc && dtype && 
2122         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2123         IFFUNC_ISISR(currFunc->type) &&
2124         !ic->bankSaved) 
2125
2126         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2127
2128 }
2129 /*-----------------------------------------------------------------*/
2130 /* unsaveRegisters - pop the pushed registers                      */
2131 /*-----------------------------------------------------------------*/
2132 static void unsaveRegisters (iCode *ic)
2133 {
2134     int i;
2135     bitVect *rsave;
2136
2137     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2138     /* find the registers in use at this time 
2139     and push them away to safety */
2140     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2141                           ic->rUsed);
2142     
2143     if (options.useXstack) {
2144         pic14_emitcode("mov","r0,%s",spname);   
2145         for (i =  pic14_nRegs ; i >= 0 ; i--) {
2146             if (bitVectBitValue(rsave,i)) {
2147                 pic14_emitcode("dec","r0");
2148                 pic14_emitcode("movx","a,@r0");
2149                 if (i == R0_IDX)
2150                     pic14_emitcode("mov","b,a");
2151                 else
2152                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2153             }       
2154
2155         }
2156         pic14_emitcode("mov","%s,r0",spname);
2157         if (bitVectBitValue(rsave,R0_IDX))
2158             pic14_emitcode("mov","r0,b");
2159     } //else
2160     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2161     //    if (bitVectBitValue(rsave,i))
2162     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2163     //}
2164
2165 }  
2166
2167
2168 /*-----------------------------------------------------------------*/
2169 /* pushSide -                                                      */
2170 /*-----------------------------------------------------------------*/
2171 static void pushSide(operand * oper, int size)
2172 {
2173 #if 0
2174         int offset = 0;
2175     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2176         while (size--) {
2177                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2178                 if (AOP_TYPE(oper) != AOP_REG &&
2179                     AOP_TYPE(oper) != AOP_DIR &&
2180                     strcmp(l,"a") ) {
2181                         pic14_emitcode("mov","a,%s",l);
2182                         pic14_emitcode("push","acc");
2183                 } else
2184                         pic14_emitcode("push","%s",l);
2185         }
2186 #endif
2187 }
2188
2189 /*-----------------------------------------------------------------*/
2190 /* assignResultValue -                                             */
2191 /*-----------------------------------------------------------------*/
2192 static void assignResultValue(operand * oper)
2193 {
2194   int size = AOP_SIZE(oper);
2195
2196   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2197
2198   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2199
2200   if(!GpsuedoStkPtr) {
2201     /* The last byte in the assignment is in W */
2202     size--;
2203     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2204     GpsuedoStkPtr++;
2205   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2206   }
2207
2208   while (size--) {
2209     emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
2210     GpsuedoStkPtr++;
2211     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2212   }
2213 }
2214
2215
2216 /*-----------------------------------------------------------------*/
2217 /* genIpush - genrate code for pushing this gets a little complex  */
2218 /*-----------------------------------------------------------------*/
2219 static void genIpush (iCode *ic)
2220 {
2221
2222   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2223 #if 0
2224     int size, offset = 0 ;
2225     char *l;
2226
2227
2228     /* if this is not a parm push : ie. it is spill push 
2229     and spill push is always done on the local stack */
2230     if (!ic->parmPush) {
2231
2232         /* and the item is spilt then do nothing */
2233         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2234             return ;
2235
2236         aopOp(IC_LEFT(ic),ic,FALSE);
2237         size = AOP_SIZE(IC_LEFT(ic));
2238         /* push it on the stack */
2239         while(size--) {
2240             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2241             if (*l == '#') {
2242                 MOVA(l);
2243                 l = "acc";
2244             }
2245             pic14_emitcode("push","%s",l);
2246         }
2247         return ;        
2248     }
2249
2250     /* this is a paramter push: in this case we call
2251     the routine to find the call and save those
2252     registers that need to be saved */   
2253     saveRegisters(ic);
2254
2255     /* then do the push */
2256     aopOp(IC_LEFT(ic),ic,FALSE);
2257
2258
2259         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2260     size = AOP_SIZE(IC_LEFT(ic));
2261
2262     while (size--) {
2263         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2264         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2265             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2266             strcmp(l,"a") ) {
2267             pic14_emitcode("mov","a,%s",l);
2268             pic14_emitcode("push","acc");
2269         } else
2270             pic14_emitcode("push","%s",l);
2271     }       
2272
2273     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2274 #endif
2275 }
2276
2277 /*-----------------------------------------------------------------*/
2278 /* genIpop - recover the registers: can happen only for spilling   */
2279 /*-----------------------------------------------------------------*/
2280 static void genIpop (iCode *ic)
2281 {
2282   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2283 #if 0
2284     int size,offset ;
2285
2286
2287     /* if the temp was not pushed then */
2288     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2289         return ;
2290
2291     aopOp(IC_LEFT(ic),ic,FALSE);
2292     size = AOP_SIZE(IC_LEFT(ic));
2293     offset = (size-1);
2294     while (size--) 
2295         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2296                                    FALSE,TRUE));
2297
2298     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2299 #endif
2300 }
2301
2302 /*-----------------------------------------------------------------*/
2303 /* unsaverbank - restores the resgister bank from stack            */
2304 /*-----------------------------------------------------------------*/
2305 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2306 {
2307   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2308 #if 0
2309     int i;
2310     asmop *aop ;
2311     regs *r = NULL;
2312
2313     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2314     if (popPsw) {
2315         if (options.useXstack) {
2316             aop = newAsmop(0);
2317             r = getFreePtr(ic,&aop,FALSE);
2318             
2319             
2320             pic14_emitcode("mov","%s,_spx",r->name);
2321             pic14_emitcode("movx","a,@%s",r->name);
2322             pic14_emitcode("mov","psw,a");
2323             pic14_emitcode("dec","%s",r->name);
2324             
2325         }else
2326             pic14_emitcode ("pop","psw");
2327     }
2328
2329     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2330         if (options.useXstack) {       
2331             pic14_emitcode("movx","a,@%s",r->name);
2332             //pic14_emitcode("mov","(%s+%d),a",
2333             //       regspic14[i].base,8*bank+regspic14[i].offset);
2334             pic14_emitcode("dec","%s",r->name);
2335
2336         } else 
2337           pic14_emitcode("pop",""); //"(%s+%d)",
2338         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2339     }
2340
2341     if (options.useXstack) {
2342
2343         pic14_emitcode("mov","_spx,%s",r->name);
2344         freeAsmop(NULL,aop,ic,TRUE);
2345
2346     }
2347 #endif 
2348 }
2349
2350 /*-----------------------------------------------------------------*/
2351 /* saverbank - saves an entire register bank on the stack          */
2352 /*-----------------------------------------------------------------*/
2353 static void saverbank (int bank, iCode *ic, bool pushPsw)
2354 {
2355   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2356 #if 0
2357     int i;
2358     asmop *aop ;
2359     regs *r = NULL;
2360
2361     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2362     if (options.useXstack) {
2363
2364         aop = newAsmop(0);
2365         r = getFreePtr(ic,&aop,FALSE);  
2366         pic14_emitcode("mov","%s,_spx",r->name);
2367
2368     }
2369
2370     for (i = 0 ; i < pic14_nRegs ;i++) {
2371         if (options.useXstack) {
2372             pic14_emitcode("inc","%s",r->name);
2373             //pic14_emitcode("mov","a,(%s+%d)",
2374             //         regspic14[i].base,8*bank+regspic14[i].offset);
2375             pic14_emitcode("movx","@%s,a",r->name);           
2376         } else 
2377           pic14_emitcode("push","");// "(%s+%d)",
2378                      //regspic14[i].base,8*bank+regspic14[i].offset);
2379     }
2380     
2381     if (pushPsw) {
2382         if (options.useXstack) {
2383             pic14_emitcode("mov","a,psw");
2384             pic14_emitcode("movx","@%s,a",r->name);     
2385             pic14_emitcode("inc","%s",r->name);
2386             pic14_emitcode("mov","_spx,%s",r->name);       
2387             freeAsmop (NULL,aop,ic,TRUE);
2388             
2389         } else
2390             pic14_emitcode("push","psw");
2391         
2392         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2393     }
2394     ic->bankSaved = 1;
2395 #endif
2396 }
2397
2398 /*-----------------------------------------------------------------*/
2399 /* genCall - generates a call statement                            */
2400 /*-----------------------------------------------------------------*/
2401 static void genCall (iCode *ic)
2402 {
2403   sym_link *dtype;   
2404
2405   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2406
2407   /* if caller saves & we have not saved then */
2408   if (!ic->regsSaved)
2409     saveRegisters(ic);
2410
2411   /* if we are calling a function that is not using
2412      the same register bank then we need to save the
2413      destination registers on the stack */
2414   dtype = operandType(IC_LEFT(ic));
2415   if (currFunc && dtype && 
2416       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2417       IFFUNC_ISISR(currFunc->type) &&
2418       !ic->bankSaved) 
2419
2420     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2421
2422   /* if send set is not empty the assign */
2423   if (_G.sendSet) {
2424     iCode *sic;
2425     /* For the Pic port, there is no data stack.
2426      * So parameters passed to functions are stored
2427      * in registers. (The pCode optimizer will get
2428      * rid of most of these :).
2429      */
2430     int psuedoStkPtr=-1; 
2431     int firstTimeThruLoop = 1;
2432
2433     _G.sendSet = reverseSet(_G.sendSet);
2434
2435     /* First figure how many parameters are getting passed */
2436     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2437          sic = setNextItem(_G.sendSet)) {
2438
2439       aopOp(IC_LEFT(sic),sic,FALSE);
2440       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2441       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2442     }
2443
2444     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2445          sic = setNextItem(_G.sendSet)) {
2446       int size, offset = 0;
2447
2448       aopOp(IC_LEFT(sic),sic,FALSE);
2449       size = AOP_SIZE(IC_LEFT(sic));
2450
2451       while (size--) {
2452         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2453                              AopType(AOP_TYPE(IC_LEFT(sic))));
2454
2455         if(!firstTimeThruLoop) {
2456           /* If this is not the first time we've been through the loop
2457            * then we need to save the parameter in a temporary
2458            * register. The last byte of the last parameter is
2459            * passed in W. */
2460           emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr));
2461
2462         }
2463         firstTimeThruLoop=0;
2464
2465         //if (strcmp(l,fReturn[offset])) {
2466         mov2w (AOP(IC_LEFT(sic)),  offset);
2467 /*
2468         if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
2469              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2470           emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset));
2471         else
2472           emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset));
2473 */
2474         //}
2475         offset++;
2476       }
2477       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2478     }
2479     _G.sendSet = NULL;
2480   }
2481   /* make the call */
2482   emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2483                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2484                                       OP_SYMBOL(IC_LEFT(ic))->name));
2485
2486   GpsuedoStkPtr=0;
2487   /* if we need assign a result value */
2488   if ((IS_ITEMP(IC_RESULT(ic)) && 
2489        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2490         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2491       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2492
2493     _G.accInUse++;
2494     aopOp(IC_RESULT(ic),ic,FALSE);
2495     _G.accInUse--;
2496
2497     assignResultValue(IC_RESULT(ic));
2498
2499     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2500                          AopType(AOP_TYPE(IC_RESULT(ic))));
2501                 
2502     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2503   }
2504
2505   /* adjust the stack for parameters if 
2506      required */
2507   if (ic->parmBytes) {
2508     int i;
2509     if (ic->parmBytes > 3) {
2510       pic14_emitcode("mov","a,%s",spname);
2511       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2512       pic14_emitcode("mov","%s,a",spname);
2513     } else 
2514       for ( i = 0 ; i <  ic->parmBytes ;i++)
2515         pic14_emitcode("dec","%s",spname);
2516
2517   }
2518
2519   /* if register bank was saved then pop them */
2520   if (ic->bankSaved)
2521     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2522
2523   /* if we hade saved some registers then unsave them */
2524   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2525     unsaveRegisters (ic);
2526
2527
2528 }
2529
2530 /*-----------------------------------------------------------------*/
2531 /* genPcall - generates a call by pointer statement                */
2532 /*-----------------------------------------------------------------*/
2533 static void genPcall (iCode *ic)
2534 {
2535     sym_link *dtype;
2536     symbol *albl = newiTempLabel(NULL);
2537     symbol *blbl = newiTempLabel(NULL);
2538     PIC_OPCODE poc;
2539     operand *left;
2540
2541     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2542     /* if caller saves & we have not saved then */
2543     if (!ic->regsSaved)
2544         saveRegisters(ic);
2545
2546     /* if we are calling a function that is not using
2547     the same register bank then we need to save the
2548     destination registers on the stack */
2549     dtype = operandType(IC_LEFT(ic));
2550     if (currFunc && dtype && 
2551         IFFUNC_ISISR(currFunc->type) &&
2552         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2553         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2554
2555     left = IC_LEFT(ic);
2556     aopOp(left,ic,FALSE);
2557     DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2558
2559     pushSide(IC_LEFT(ic), FPTRSIZE);
2560
2561     /* if send set is not empty, assign parameters */
2562     if (_G.sendSet) {
2563
2564         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2565         /* no way to pass args - W always gets used to make the call */
2566     }
2567 /* first idea - factor out a common helper function and call it.
2568    But don't know how to get it generated only once in its own block
2569
2570     if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2571             char *rname;
2572             char *buffer;
2573             rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2574             DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2575             buffer = Safe_calloc(1,strlen(rname)+16);
2576             sprintf(buffer, "%s_goto_helper", rname);
2577             addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2578             free(buffer);
2579     }
2580 */
2581     emitpcode(POC_CALL,popGetLabel(albl->key));
2582     emitpcodePagesel(popGetLabel(blbl->key)->name); /* Must restore PCLATH before goto, without destroying W */
2583     emitpcode(POC_GOTO,popGetLabel(blbl->key));
2584     emitpLabel(albl->key);
2585
2586     poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
2587     
2588     emitpcode(poc,popGet(AOP(left),1));
2589     emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2590     emitpcode(poc,popGet(AOP(left),0));
2591     emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2592
2593     emitpLabel(blbl->key);
2594
2595     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2596
2597     /* if we need to assign a result value */
2598     if ((IS_ITEMP(IC_RESULT(ic)) &&
2599          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2600           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2601         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2602
2603         _G.accInUse++;
2604         aopOp(IC_RESULT(ic),ic,FALSE);
2605         _G.accInUse--;
2606         
2607         assignResultValue(IC_RESULT(ic));
2608
2609         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2610     }
2611
2612     /* if register bank was saved then unsave them */
2613     if (currFunc && dtype && 
2614         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2615         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2616
2617     /* if we hade saved some registers then
2618     unsave them */
2619     if (ic->regsSaved)
2620         unsaveRegisters (ic);
2621
2622 }
2623
2624 /*-----------------------------------------------------------------*/
2625 /* resultRemat - result  is rematerializable                       */
2626 /*-----------------------------------------------------------------*/
2627 static int resultRemat (iCode *ic)
2628 {
2629   //    DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2630   if (SKIP_IC(ic) || ic->op == IFX)
2631     return 0;
2632
2633   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2634     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2635     if (sym->remat && !POINTER_SET(ic)) 
2636       return 1;
2637   }
2638
2639   return 0;
2640 }
2641
2642 #if defined(__BORLANDC__) || defined(_MSC_VER)
2643 #define STRCASECMP stricmp
2644 #else
2645 #define STRCASECMP strcasecmp
2646 #endif
2647
2648 #if 0
2649 /*-----------------------------------------------------------------*/
2650 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2651 /*-----------------------------------------------------------------*/
2652 static bool inExcludeList(char *s)
2653 {
2654   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2655     int i =0;
2656     
2657     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2658     if (options.excludeRegs[i] &&
2659     STRCASECMP(options.excludeRegs[i],"none") == 0)
2660         return FALSE ;
2661
2662     for ( i = 0 ; options.excludeRegs[i]; i++) {
2663         if (options.excludeRegs[i] &&
2664         STRCASECMP(s,options.excludeRegs[i]) == 0)
2665             return TRUE;
2666     }
2667     return FALSE ;
2668 }
2669 #endif
2670
2671 /*-----------------------------------------------------------------*/
2672 /* genFunction - generated code for function entry                 */
2673 /*-----------------------------------------------------------------*/
2674 static void genFunction (iCode *ic)
2675 {
2676     symbol *sym;
2677     sym_link *ftype;
2678
2679     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2680
2681     labelOffset += (max_key+4);
2682     max_key=0;
2683     GpsuedoStkPtr=0;
2684     _G.nRegsSaved = 0;
2685     /* create the function header */
2686     pic14_emitcode(";","-----------------------------------------");
2687     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2688     pic14_emitcode(";","-----------------------------------------");
2689
2690     pic14_emitcode("","%s:",sym->rname);
2691     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2692
2693     ftype = operandType(IC_LEFT(ic));
2694
2695     /* if critical function then turn interrupts off */
2696     if (IFFUNC_ISCRITICAL(ftype))
2697         pic14_emitcode("clr","ea");
2698
2699     /* here we need to generate the equates for the
2700        register bank if required */
2701 #if 0
2702     if (FUNC_REGBANK(ftype) != rbank) {
2703         int i ;
2704
2705         rbank = FUNC_REGBANK(ftype);
2706         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2707             if (strcmp(regspic14[i].base,"0") == 0)
2708                 pic14_emitcode("","%s = 0x%02x",
2709                          regspic14[i].dname,
2710                          8*rbank+regspic14[i].offset);
2711             else
2712                 pic14_emitcode ("","%s = %s + 0x%02x",
2713                           regspic14[i].dname,
2714                           regspic14[i].base,
2715                           8*rbank+regspic14[i].offset);
2716         }
2717     }
2718 #endif
2719
2720     /* if this is an interrupt service routine */
2721     if (IFFUNC_ISISR(sym->type)) {
2722 /*  already done in pic14createInterruptVect() - delete me
2723       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2724       emitpcodeNULLop(POC_NOP);
2725       emitpcodeNULLop(POC_NOP);
2726       emitpcodeNULLop(POC_NOP);
2727 */
2728       emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2729       emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2730       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2731       emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2732       emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2733       emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2734       emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* durring an interrupt PCLATH must be cleared before a goto or call statement */
2735
2736       pBlockConvert2ISR(pb);
2737 #if 0  
2738         if (!inExcludeList("acc"))          
2739             pic14_emitcode ("push","acc");      
2740         if (!inExcludeList("b"))
2741             pic14_emitcode ("push","b");
2742         if (!inExcludeList("dpl"))
2743             pic14_emitcode ("push","dpl");
2744         if (!inExcludeList("dph"))
2745             pic14_emitcode ("push","dph");
2746         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2747         {
2748             pic14_emitcode ("push", "dpx");
2749             /* Make sure we're using standard DPTR */
2750             pic14_emitcode ("push", "dps");
2751             pic14_emitcode ("mov", "dps, #0x00");
2752             if (options.stack10bit)
2753             {   
2754                 /* This ISR could conceivably use DPTR2. Better save it. */
2755                 pic14_emitcode ("push", "dpl1");
2756                 pic14_emitcode ("push", "dph1");
2757                 pic14_emitcode ("push", "dpx1");
2758             }
2759         }
2760         /* if this isr has no bank i.e. is going to
2761            run with bank 0 , then we need to save more
2762            registers :-) */
2763         if (!FUNC_REGBANK(sym->type)) {
2764
2765             /* if this function does not call any other
2766                function then we can be economical and
2767                save only those registers that are used */
2768             if (! IFFUNC_HASFCALL(sym->type)) {
2769                 int i;
2770
2771                 /* if any registers used */
2772                 if (sym->regsUsed) {
2773                     /* save the registers used */
2774                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2775                         if (bitVectBitValue(sym->regsUsed,i) ||
2776                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2777                           pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);                         
2778                     }
2779                 }
2780                 
2781             } else {
2782                 /* this function has  a function call cannot
2783                    determines register usage so we will have the
2784                    entire bank */
2785                 saverbank(0,ic,FALSE);
2786             }       
2787         }
2788 #endif
2789     } else {
2790         /* if callee-save to be used for this function
2791            then save the registers being used in this function */
2792         if (IFFUNC_CALLEESAVES(sym->type)) {
2793             int i;
2794             
2795             /* if any registers used */
2796             if (sym->regsUsed) {
2797                 /* save the registers used */
2798                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2799                     if (bitVectBitValue(sym->regsUsed,i) ||
2800                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2801                       //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2802                         _G.nRegsSaved++;
2803                     }
2804                 }
2805             }
2806         }
2807     }
2808
2809     /* set the register bank to the desired value */
2810     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2811         pic14_emitcode("push","psw");
2812         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2813     }
2814
2815     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2816
2817         if (options.useXstack) {
2818             pic14_emitcode("mov","r0,%s",spname);
2819             pic14_emitcode("mov","a,_bp");
2820             pic14_emitcode("movx","@r0,a");
2821             pic14_emitcode("inc","%s",spname);
2822         }
2823         else
2824         {
2825             /* set up the stack */
2826             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2827         }
2828         pic14_emitcode ("mov","_bp,%s",spname);
2829     }
2830
2831     /* adjust the stack for the function */
2832     if (sym->stack) {
2833
2834         int i = sym->stack;
2835         if (i > 256 ) 
2836             werror(W_STACK_OVERFLOW,sym->name);
2837
2838         if (i > 3 && sym->recvSize < 4) {              
2839
2840             pic14_emitcode ("mov","a,sp");
2841             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2842             pic14_emitcode ("mov","sp,a");
2843            
2844         }
2845         else
2846             while(i--)
2847                 pic14_emitcode("inc","sp");
2848     }
2849
2850      if (sym->xstack) {
2851
2852         pic14_emitcode ("mov","a,_spx");
2853         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2854         pic14_emitcode ("mov","_spx,a");
2855     }    
2856
2857 }
2858
2859 /*-----------------------------------------------------------------*/
2860 /* genEndFunction - generates epilogue for functions               */
2861 /*-----------------------------------------------------------------*/
2862 static void genEndFunction (iCode *ic)
2863 {
2864     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2865
2866     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2867
2868     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2869     {
2870         pic14_emitcode ("mov","%s,_bp",spname);
2871     }
2872
2873     /* if use external stack but some variables were
2874     added to the local stack then decrement the
2875     local stack */
2876     if (options.useXstack && sym->stack) {      
2877         pic14_emitcode("mov","a,sp");
2878         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2879         pic14_emitcode("mov","sp,a");
2880     }
2881
2882
2883     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2884         if (options.useXstack) {
2885             pic14_emitcode("mov","r0,%s",spname);
2886             pic14_emitcode("movx","a,@r0");
2887             pic14_emitcode("mov","_bp,a");
2888             pic14_emitcode("dec","%s",spname);
2889         }
2890         else
2891         {
2892             pic14_emitcode ("pop","_bp");
2893         }
2894     }
2895
2896     /* restore the register bank  */    
2897     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2898         pic14_emitcode ("pop","psw");
2899
2900     if (IFFUNC_ISISR(sym->type)) {
2901
2902         /* now we need to restore the registers */
2903         /* if this isr has no bank i.e. is going to
2904            run with bank 0 , then we need to save more
2905            registers :-) */
2906         if (!FUNC_REGBANK(sym->type)) {
2907             
2908             /* if this function does not call any other
2909                function then we can be economical and
2910                save only those registers that are used */
2911             if (! IFFUNC_HASFCALL(sym->type)) {
2912                 int i;
2913                 
2914                 /* if any registers used */
2915                 if (sym->regsUsed) {
2916                     /* save the registers used */
2917                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2918                         if (bitVectBitValue(sym->regsUsed,i) ||
2919                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2920                           pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2921                     }
2922                 }
2923                 
2924             } else {
2925                 /* this function has  a function call cannot
2926                    determines register usage so we will have the
2927                    entire bank */
2928                 unsaverbank(0,ic,FALSE);
2929             }       
2930         }
2931 #if 0
2932         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2933         {
2934             if (options.stack10bit)
2935             {
2936                 pic14_emitcode ("pop", "dpx1");
2937                 pic14_emitcode ("pop", "dph1");
2938                 pic14_emitcode ("pop", "dpl1");
2939             }   
2940             pic14_emitcode ("pop", "dps");
2941             pic14_emitcode ("pop", "dpx");
2942         }
2943         if (!inExcludeList("dph"))
2944             pic14_emitcode ("pop","dph");
2945         if (!inExcludeList("dpl"))
2946             pic14_emitcode ("pop","dpl");
2947         if (!inExcludeList("b"))
2948             pic14_emitcode ("pop","b");
2949         if (!inExcludeList("acc"))
2950             pic14_emitcode ("pop","acc");
2951
2952         if (IFFUNC_ISCRITICAL(sym->type))
2953             pic14_emitcode("setb","ea");
2954 #endif
2955
2956         /* if debug then send end of function */
2957 /*      if (options.debug && currFunc) { */
2958         if (currFunc) {
2959             _G.debugLine = 1;
2960             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2961                      FileBaseName(ic->filename),currFunc->lastLine,
2962                      ic->level,ic->block); 
2963             if (IS_STATIC(currFunc->etype))         
2964                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2965             else
2966                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2967             _G.debugLine = 0;
2968         }
2969
2970         pic14_emitcode ("reti","");
2971         emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2972         emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2973         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2974         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2975         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2976         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2977         emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2978         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2979         emitpcodeNULLop(POC_RETFIE);
2980     }
2981     else {
2982         if (IFFUNC_ISCRITICAL(sym->type))
2983             pic14_emitcode("setb","ea");
2984         
2985         if (IFFUNC_CALLEESAVES(sym->type)) {
2986             int i;
2987             
2988             /* if any registers used */
2989             if (sym->regsUsed) {
2990                 /* save the registers used */
2991                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2992                     if (bitVectBitValue(sym->regsUsed,i) ||
2993                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2994                       pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2995                 }
2996             }
2997             
2998         }
2999
3000         /* if debug then send end of function */
3001         if (currFunc) {
3002             _G.debugLine = 1;
3003             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
3004                      FileBaseName(ic->filename),currFunc->lastLine,
3005                      ic->level,ic->block); 
3006             if (IS_STATIC(currFunc->etype))         
3007                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3008             else
3009                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3010             _G.debugLine = 0;
3011         }
3012
3013         pic14_emitcode ("return","");
3014         emitpcodeNULLop(POC_RETURN);
3015
3016         /* Mark the end of a function */
3017         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
3018     }
3019
3020 }
3021
3022 /*-----------------------------------------------------------------*/
3023 /* genRet - generate code for return statement                     */
3024 /*-----------------------------------------------------------------*/
3025 static void genRet (iCode *ic)
3026 {
3027   int size,offset = 0 , pushed = 0;
3028     
3029   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3030   /* if we have no return value then
3031      just generate the "ret" */
3032   if (!IC_LEFT(ic)) 
3033     goto jumpret;       
3034     
3035   /* we have something to return then
3036      move the return value into place */
3037   aopOp(IC_LEFT(ic),ic,FALSE);
3038   size = AOP_SIZE(IC_LEFT(ic));
3039     
3040   while (size--) {
3041     char *l ;
3042     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3043       /* #NOCHANGE */
3044       l = aopGet(AOP(IC_LEFT(ic)),offset++,
3045                  FALSE,TRUE);
3046       pic14_emitcode("push","%s",l);
3047       pushed++;
3048     } else {
3049       l = aopGet(AOP(IC_LEFT(ic)),offset,
3050                  FALSE,FALSE);
3051       if (strcmp(fReturn[offset],l)) {
3052       if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
3053            AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
3054           ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3055           ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3056           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
3057         }else {
3058           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3059         }
3060         if(size) {
3061           emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
3062         }
3063         offset++;
3064       }
3065     }
3066   }    
3067
3068   if (pushed) {
3069     while(pushed) {
3070       pushed--;
3071       if (strcmp(fReturn[pushed],"a"))
3072         pic14_emitcode("pop",fReturn[pushed]);
3073       else
3074         pic14_emitcode("pop","acc");
3075     }
3076   }
3077   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3078     
3079  jumpret:
3080   /* generate a jump to the return label
3081      if the next is not the return statement */
3082   if (!(ic->next && ic->next->op == LABEL &&
3083         IC_LABEL(ic->next) == returnLabel)) {
3084         
3085     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3086     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3087   }
3088     
3089 }
3090
3091 /*-----------------------------------------------------------------*/
3092 /* genLabel - generates a label                                    */
3093 /*-----------------------------------------------------------------*/
3094 static void genLabel (iCode *ic)
3095 {
3096     /* special case never generate */
3097     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3098     if (IC_LABEL(ic) == entryLabel)
3099         return ;
3100
3101     emitpLabel(IC_LABEL(ic)->key);
3102     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3103 }
3104
3105 /*-----------------------------------------------------------------*/
3106 /* genGoto - generates a goto                                      */
3107 /*-----------------------------------------------------------------*/
3108 //tsd
3109 static void genGoto (iCode *ic)
3110 {
3111   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3112   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3113 }
3114
3115
3116 /*-----------------------------------------------------------------*/
3117 /* genMultbits :- multiplication of bits                           */
3118 /*-----------------------------------------------------------------*/
3119 static void genMultbits (operand *left, 
3120                          operand *right, 
3121                          operand *result)
3122 {
3123   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3124
3125   if(!pic14_sameRegs(AOP(result),AOP(right)))
3126     emitpcode(POC_BSF,  popGet(AOP(result),0));
3127
3128   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3129   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3130   emitpcode(POC_BCF,  popGet(AOP(result),0));
3131
3132 }
3133
3134
3135 /*-----------------------------------------------------------------*/
3136 /* genMultOneByte : 8 bit multiplication & division                */
3137 /*-----------------------------------------------------------------*/
3138 static void genMultOneByte (operand *left,
3139                             operand *right,
3140                             operand *result)
3141 {
3142   sym_link *opetype = operandType(result);
3143
3144   // symbol *lbl ;
3145   int size,offset;
3146
3147   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3148   DEBUGpic14_AopType(__LINE__,left,right,result);
3149   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3150
3151   /* (if two literals, the value is computed before) */
3152   /* if one literal, literal on the right */
3153   if (AOP_TYPE(left) == AOP_LIT){
3154     operand *t = right;
3155     right = left;
3156     left = t;
3157   }
3158
3159   size = AOP_SIZE(result);
3160   if(size == 1) {
3161
3162     if (AOP_TYPE(right) == AOP_LIT){
3163       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3164                      aopGet(AOP(right),0,FALSE,FALSE), 
3165                      aopGet(AOP(left),0,FALSE,FALSE), 
3166                      aopGet(AOP(result),0,FALSE,FALSE));
3167       pic14_emitcode("call","genMultLit");
3168     } else {
3169       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3170                      aopGet(AOP(right),0,FALSE,FALSE), 
3171                      aopGet(AOP(left),0,FALSE,FALSE), 
3172                      aopGet(AOP(result),0,FALSE,FALSE));
3173       pic14_emitcode("call","genMult8X8_8");
3174
3175     }
3176     genMult8X8_8 (left, right,result);
3177
3178
3179     /* signed or unsigned */
3180     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3181     //l = aopGet(AOP(left),0,FALSE,FALSE);
3182     //MOVA(l);       
3183     //pic14_emitcode("mul","ab");
3184     /* if result size = 1, mul signed = mul unsigned */
3185     //aopPut(AOP(result),"a",0);
3186
3187   } else {  // (size > 1)
3188
3189     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3190                    aopGet(AOP(right),0,FALSE,FALSE), 
3191                    aopGet(AOP(left),0,FALSE,FALSE), 
3192                    aopGet(AOP(result),0,FALSE,FALSE));
3193
3194     if (SPEC_USIGN(opetype)){
3195       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3196       genUMult8X8_16 (left, right, result, NULL);
3197
3198       if (size > 2) {
3199         /* for filling the MSBs */
3200         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3201         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3202       }
3203     }
3204     else{
3205       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3206
3207       pic14_emitcode("mov","a,b");
3208
3209       /* adjust the MSB if left or right neg */
3210
3211       /* if one literal */
3212       if (AOP_TYPE(right) == AOP_LIT){
3213         pic14_emitcode("multiply ","right is a lit");
3214         /* AND literal negative */
3215         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3216           /* adjust MSB (c==0 after mul) */
3217           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3218         }
3219       }
3220       else{
3221         genSMult8X8_16 (left, right, result, NULL);
3222       }
3223
3224       if(size > 2){
3225         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3226         /* get the sign */
3227         pic14_emitcode("rlc","a");
3228         pic14_emitcode("subb","a,acc");
3229       }
3230     }
3231
3232     size -= 2;   
3233     offset = 2;
3234     if (size > 0)
3235       while (size--)
3236         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3237     //aopPut(AOP(result),"a",offset++);
3238   }
3239 }
3240
3241 /*-----------------------------------------------------------------*/
3242 /* genMult - generates code for multiplication                     */
3243 /*-----------------------------------------------------------------*/
3244 static void genMult (iCode *ic)
3245 {
3246     operand *left = IC_LEFT(ic);
3247     operand *right = IC_RIGHT(ic);
3248     operand *result= IC_RESULT(ic);   
3249
3250     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3251     /* assign the amsops */
3252     aopOp (left,ic,FALSE);
3253     aopOp (right,ic,FALSE);
3254     aopOp (result,ic,TRUE);
3255
3256   DEBUGpic14_AopType(__LINE__,left,right,result);
3257
3258     /* special cases first */
3259     /* both are bits */
3260     if (AOP_TYPE(left) == AOP_CRY &&
3261         AOP_TYPE(right)== AOP_CRY) {
3262         genMultbits(left,right,result);
3263         goto release ;
3264     }
3265
3266     /* if both are of size == 1 */
3267     if (AOP_SIZE(left) == 1 &&
3268         AOP_SIZE(right) == 1 ) {
3269         genMultOneByte(left,right,result);
3270         goto release ;
3271     }
3272
3273     pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3274
3275     /* should have been converted to function call */
3276     //assert(0) ;
3277
3278 release :
3279     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3280     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3281     freeAsmop(result,NULL,ic,TRUE); 
3282 }
3283
3284 /*-----------------------------------------------------------------*/
3285 /* genDivbits :- division of bits                                  */
3286 /*-----------------------------------------------------------------*/
3287 static void genDivbits (operand *left, 
3288                         operand *right, 
3289                         operand *result)
3290 {
3291
3292     char *l;
3293
3294     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3295     /* the result must be bit */    
3296     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3297     l = aopGet(AOP(left),0,FALSE,FALSE);
3298
3299     MOVA(l);    
3300
3301     pic14_emitcode("div","ab");
3302     pic14_emitcode("rrc","a");
3303     aopPut(AOP(result),"c",0);
3304 }
3305
3306 /*-----------------------------------------------------------------*/
3307 /* genDivOneByte : 8 bit division                                  */
3308 /*-----------------------------------------------------------------*/
3309 static void genDivOneByte (operand *left,
3310                            operand *right,
3311                            operand *result)
3312 {
3313     sym_link *opetype = operandType(result);
3314     char *l ;
3315     symbol *lbl ;
3316     int size,offset;
3317
3318     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3319     size = AOP_SIZE(result) - 1;
3320     offset = 1;
3321     /* signed or unsigned */
3322     if (SPEC_USIGN(opetype)) {
3323         /* unsigned is easy */
3324         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3325         l = aopGet(AOP(left),0,FALSE,FALSE);
3326         MOVA(l);        
3327         pic14_emitcode("div","ab");
3328         aopPut(AOP(result),"a",0);
3329         while (size--)
3330             aopPut(AOP(result),zero,offset++);
3331         return ;
3332     }
3333
3334     /* signed is a little bit more difficult */
3335
3336     /* save the signs of the operands */
3337     l = aopGet(AOP(left),0,FALSE,FALSE);    
3338     MOVA(l);    
3339     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3340     pic14_emitcode("push","acc"); /* save it on the stack */
3341
3342     /* now sign adjust for both left & right */
3343     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3344     MOVA(l);       
3345     lbl = newiTempLabel(NULL);
3346     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3347     pic14_emitcode("cpl","a");   
3348     pic14_emitcode("inc","a");
3349     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3350     pic14_emitcode("mov","b,a");
3351
3352     /* sign adjust left side */
3353     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3354     MOVA(l);
3355
3356     lbl = newiTempLabel(NULL);
3357     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3358     pic14_emitcode("cpl","a");
3359     pic14_emitcode("inc","a");
3360     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3361
3362     /* now the division */
3363     pic14_emitcode("div","ab");
3364     /* we are interested in the lower order
3365     only */
3366     pic14_emitcode("mov","b,a");
3367     lbl = newiTempLabel(NULL);
3368     pic14_emitcode("pop","acc");   
3369     /* if there was an over flow we don't 
3370     adjust the sign of the result */
3371     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3372     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3373     CLRC;
3374     pic14_emitcode("clr","a");
3375     pic14_emitcode("subb","a,b");
3376     pic14_emitcode("mov","b,a");
3377     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3378
3379     /* now we are done */
3380     aopPut(AOP(result),"b",0);
3381     if(size > 0){
3382         pic14_emitcode("mov","c,b.7");
3383         pic14_emitcode("subb","a,acc");   
3384     }
3385     while (size--)
3386         aopPut(AOP(result),"a",offset++);
3387
3388 }
3389
3390 /*-----------------------------------------------------------------*/
3391 /* genDiv - generates code for division                            */
3392 /*-----------------------------------------------------------------*/
3393 static void genDiv (iCode *ic)
3394 {
3395     operand *left = IC_LEFT(ic);
3396     operand *right = IC_RIGHT(ic);
3397     operand *result= IC_RESULT(ic);   
3398
3399     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3400     /* assign the amsops */
3401     aopOp (left,ic,FALSE);
3402     aopOp (right,ic,FALSE);
3403     aopOp (result,ic,TRUE);
3404
3405     /* special cases first */
3406     /* both are bits */
3407     if (AOP_TYPE(left) == AOP_CRY &&
3408         AOP_TYPE(right)== AOP_CRY) {
3409         genDivbits(left,right,result);
3410         goto release ;
3411     }
3412
3413     /* if both are of size == 1 */
3414     if (AOP_SIZE(left) == 1 &&
3415         AOP_SIZE(right) == 1 ) {
3416         genDivOneByte(left,right,result);
3417         goto release ;
3418     }
3419
3420     /* should have been converted to function call */
3421     assert(0);
3422 release :
3423     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3424     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3425     freeAsmop(result,NULL,ic,TRUE); 
3426 }
3427
3428 /*-----------------------------------------------------------------*/
3429 /* genModbits :- modulus of bits                                   */
3430 /*-----------------------------------------------------------------*/
3431 static void genModbits (operand *left, 
3432                         operand *right, 
3433                         operand *result)
3434 {
3435
3436     char *l;
3437
3438     /* the result must be bit */    
3439     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3440     l = aopGet(AOP(left),0,FALSE,FALSE);
3441
3442     MOVA(l);       
3443
3444     pic14_emitcode("div","ab");
3445     pic14_emitcode("mov","a,b");
3446     pic14_emitcode("rrc","a");
3447     aopPut(AOP(result),"c",0);
3448 }
3449
3450 /*-----------------------------------------------------------------*/
3451 /* genModOneByte : 8 bit modulus                                   */
3452 /*-----------------------------------------------------------------*/
3453 static void genModOneByte (operand *left,
3454                            operand *right,
3455                            operand *result)
3456 {
3457     sym_link *opetype = operandType(result);
3458     char *l ;
3459     symbol *lbl ;
3460
3461     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3462     /* signed or unsigned */
3463     if (SPEC_USIGN(opetype)) {
3464         /* unsigned is easy */
3465         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3466         l = aopGet(AOP(left),0,FALSE,FALSE);
3467         MOVA(l);    
3468         pic14_emitcode("div","ab");
3469         aopPut(AOP(result),"b",0);
3470         return ;
3471     }
3472
3473     /* signed is a little bit more difficult */
3474
3475     /* save the signs of the operands */
3476     l = aopGet(AOP(left),0,FALSE,FALSE);    
3477     MOVA(l);
3478
3479     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3480     pic14_emitcode("push","acc"); /* save it on the stack */
3481
3482     /* now sign adjust for both left & right */
3483     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3484     MOVA(l);
3485
3486     lbl = newiTempLabel(NULL);
3487     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3488     pic14_emitcode("cpl","a");   
3489     pic14_emitcode("inc","a");
3490     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3491     pic14_emitcode("mov","b,a"); 
3492
3493     /* sign adjust left side */
3494     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3495     MOVA(l);
3496
3497     lbl = newiTempLabel(NULL);
3498     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3499     pic14_emitcode("cpl","a");   
3500     pic14_emitcode("inc","a");
3501     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3502
3503     /* now the multiplication */
3504     pic14_emitcode("div","ab");
3505     /* we are interested in the lower order
3506     only */
3507     lbl = newiTempLabel(NULL);
3508     pic14_emitcode("pop","acc");   
3509     /* if there was an over flow we don't 
3510     adjust the sign of the result */
3511     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3512     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3513     CLRC ;
3514     pic14_emitcode("clr","a");
3515     pic14_emitcode("subb","a,b");
3516     pic14_emitcode("mov","b,a");
3517     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3518
3519     /* now we are done */
3520     aopPut(AOP(result),"b",0);
3521
3522 }
3523
3524 /*-----------------------------------------------------------------*/
3525 /* genMod - generates code for division                            */
3526 /*-----------------------------------------------------------------*/
3527 static void genMod (iCode *ic)
3528 {
3529     operand *left = IC_LEFT(ic);
3530     operand *right = IC_RIGHT(ic);
3531     operand *result= IC_RESULT(ic);  
3532
3533     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3534     /* assign the amsops */
3535     aopOp (left,ic,FALSE);
3536     aopOp (right,ic,FALSE);
3537     aopOp (result,ic,TRUE);
3538
3539     /* special cases first */
3540     /* both are bits */
3541     if (AOP_TYPE(left) == AOP_CRY &&
3542         AOP_TYPE(right)== AOP_CRY) {
3543         genModbits(left,right,result);
3544         goto release ;
3545     }
3546
3547     /* if both are of size == 1 */
3548     if (AOP_SIZE(left) == 1 &&
3549         AOP_SIZE(right) == 1 ) {
3550         genModOneByte(left,right,result);
3551         goto release ;
3552     }
3553
3554     /* should have been converted to function call */
3555     assert(0);
3556
3557 release :
3558     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3559     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3560     freeAsmop(result,NULL,ic,TRUE); 
3561 }
3562
3563 /*-----------------------------------------------------------------*/
3564 /* genIfxJump :- will create a jump depending on the ifx           */
3565 /*-----------------------------------------------------------------*/
3566 /*
3567   note: May need to add parameter to indicate when a variable is in bit space.
3568 */
3569 static void genIfxJump (iCode *ic, char *jval)
3570 {
3571
3572     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3573     /* if true label then we jump if condition
3574     supplied is true */
3575     if ( IC_TRUE(ic) ) {
3576
3577         if(strcmp(jval,"a") == 0)
3578           emitSKPZ;
3579         else if (strcmp(jval,"c") == 0)
3580           emitSKPC;
3581         else {
3582           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3583           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3584         }
3585
3586         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3587         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3588
3589     }
3590     else {
3591         /* false label is present */
3592         if(strcmp(jval,"a") == 0)
3593           emitSKPNZ;
3594         else if (strcmp(jval,"c") == 0)
3595           emitSKPNC;
3596         else {
3597           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3598           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3599         }
3600
3601         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3602         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3603
3604     }
3605
3606
3607     /* mark the icode as generated */
3608     ic->generated = 1;
3609 }
3610
3611 /*-----------------------------------------------------------------*/
3612 /* genSkip                                                         */
3613 /*-----------------------------------------------------------------*/
3614 static void genSkip(iCode *ifx,int status_bit)
3615 {
3616   if(!ifx)
3617     return;
3618
3619   if ( IC_TRUE(ifx) ) {
3620     switch(status_bit) {
3621     case 'z':
3622       emitSKPNZ;
3623       break;
3624
3625     case 'c':
3626       emitSKPNC;
3627       break;
3628
3629     case 'd':
3630       emitSKPDC;
3631       break;
3632
3633     }
3634
3635     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3636     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3637
3638   } else {
3639
3640     switch(status_bit) {
3641
3642     case 'z':
3643       emitSKPZ;
3644       break;
3645
3646     case 'c':
3647       emitSKPC;
3648       break;
3649
3650     case 'd':
3651       emitSKPDC;
3652       break;
3653     }
3654     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3655     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3656
3657   }
3658
3659 }
3660
3661 /*-----------------------------------------------------------------*/
3662 /* genSkipc                                                        */
3663 /*-----------------------------------------------------------------*/
3664 static void genSkipc(resolvedIfx *rifx)
3665 {
3666   if(!rifx)
3667     return;
3668
3669   if(rifx->condition)
3670     emitSKPC;
3671   else
3672     emitSKPNC;
3673
3674   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3675   rifx->generated = 1;
3676 }
3677
3678 /*-----------------------------------------------------------------*/
3679 /* genSkipz2                                                       */
3680 /*-----------------------------------------------------------------*/
3681 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3682 {
3683   if(!rifx)
3684     return;
3685
3686   if( (rifx->condition ^ invert_condition) & 1)
3687     emitSKPZ;
3688   else
3689     emitSKPNZ;
3690
3691   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3692   rifx->generated = 1;
3693 }
3694
3695 /*-----------------------------------------------------------------*/
3696 /* genSkipz                                                        */
3697 /*-----------------------------------------------------------------*/
3698 static void genSkipz(iCode *ifx, int condition)
3699 {
3700   if(!ifx)
3701     return;
3702
3703   if(condition)
3704     emitSKPNZ;
3705   else
3706     emitSKPZ;
3707
3708   if ( IC_TRUE(ifx) )
3709     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3710   else
3711     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3712
3713   if ( IC_TRUE(ifx) )
3714     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3715   else
3716     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3717
3718 }
3719 /*-----------------------------------------------------------------*/
3720 /* genSkipCond                                                     */
3721 /*-----------------------------------------------------------------*/
3722 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3723 {
3724   if(!rifx)
3725     return;
3726
3727   if(rifx->condition)
3728     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3729   else
3730     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3731
3732
3733   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3734   rifx->generated = 1;
3735 }
3736
3737 #if 0
3738 /*-----------------------------------------------------------------*/
3739 /* genChkZeroes :- greater or less than comparison                 */
3740 /*     For each byte in a literal that is zero, inclusive or the   */
3741 /*     the corresponding byte in the operand with W                */
3742 /*     returns true if any of the bytes are zero                   */
3743 /*-----------------------------------------------------------------*/
3744 static int genChkZeroes(operand *op, int lit,  int size)
3745 {
3746
3747   int i;
3748   int flag =1;
3749
3750   while(size--) {
3751     i = (lit >> (size*8)) & 0xff;
3752
3753     if(i==0) {
3754       if(flag) 
3755         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3756       else
3757         emitpcode(POC_IORFW, popGet(AOP(op),size));
3758       flag = 0;
3759     }
3760   }
3761
3762   return (flag==0);
3763 }
3764 #endif
3765
3766 /*-----------------------------------------------------------------*/
3767 /* genCmp :- greater or less than comparison                       */
3768 /*-----------------------------------------------------------------*/
3769 static void genCmp (operand *left,operand *right,
3770                     operand *result, iCode *ifx, int sign)
3771 {
3772   int size; //, offset = 0 ;
3773   unsigned long lit = 0L,i = 0;
3774   resolvedIfx rFalseIfx;
3775   //  resolvedIfx rTrueIfx;
3776   symbol *truelbl;
3777   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3778 /*
3779   if(ifx) {
3780     DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3781     DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3782   }
3783 */
3784
3785   resolveIfx(&rFalseIfx,ifx);
3786   truelbl  = newiTempLabel(NULL);
3787   size = max(AOP_SIZE(left),AOP_SIZE(right));
3788
3789   DEBUGpic14_AopType(__LINE__,left,right,result);
3790
3791 #define _swapp
3792
3793   /* if literal is on the right then swap with left */
3794   if ((AOP_TYPE(right) == AOP_LIT)) {
3795     operand *tmp = right ;
3796     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3797     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3798 #ifdef _swapp
3799
3800     lit = (lit - 1) & mask;
3801     right = left;
3802     left = tmp;
3803     rFalseIfx.condition ^= 1;
3804 #endif
3805
3806   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3807     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3808   }
3809
3810
3811   //if(IC_TRUE(ifx) == NULL)
3812   /* if left & right are bit variables */
3813   if (AOP_TYPE(left) == AOP_CRY &&
3814       AOP_TYPE(right) == AOP_CRY ) {
3815     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3816     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3817   } else {
3818     /* subtract right from left if at the
3819        end the carry flag is set then we know that
3820        left is greater than right */
3821
3822     //    {
3823
3824     symbol *lbl  = newiTempLabel(NULL);
3825
3826 #ifndef _swapp
3827     if(AOP_TYPE(right) == AOP_LIT) {
3828
3829       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3830
3831       DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3832
3833       /* special cases */
3834
3835       if(lit == 0) {
3836
3837         if(sign != 0) 
3838           genSkipCond(&rFalseIfx,left,size-1,7);
3839         else 
3840           /* no need to compare to 0...*/
3841           /* NOTE: this is a de-generate compare that most certainly 
3842            *       creates some dead code. */
3843           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3844
3845         if(ifx) ifx->generated = 1;
3846         return;
3847
3848       }
3849       size--;
3850
3851       if(size == 0) {
3852         //i = (lit >> (size*8)) & 0xff;
3853         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3854         
3855         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3856
3857         i = ((0-lit) & 0xff);
3858         if(sign) {
3859           if( i == 0x81) { 
3860             /* lit is 0x7f, all signed chars are less than
3861              * this except for 0x7f itself */
3862             emitpcode(POC_XORLW, popGetLit(0x7f));
3863             genSkipz2(&rFalseIfx,0);
3864           } else {
3865             emitpcode(POC_ADDLW, popGetLit(0x80));
3866             emitpcode(POC_ADDLW, popGetLit(i^0x80));
3867             genSkipc(&rFalseIfx);
3868           }
3869
3870         } else {
3871           if(lit == 1) {
3872             genSkipz2(&rFalseIfx,1);
3873           } else {
3874             emitpcode(POC_ADDLW, popGetLit(i));
3875             genSkipc(&rFalseIfx);
3876           }
3877         }
3878
3879         if(ifx) ifx->generated = 1;
3880         return;
3881       }
3882
3883       /* chars are out of the way. now do ints and longs */
3884
3885
3886       DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3887         
3888       /* special cases */
3889
3890       if(sign) {
3891
3892         if(lit == 0) {
3893           genSkipCond(&rFalseIfx,left,size,7);
3894           if(ifx) ifx->generated = 1;
3895           return;
3896         }
3897
3898         if(lit <0x100) {
3899           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3900
3901           //rFalseIfx.condition ^= 1;
3902           //genSkipCond(&rFalseIfx,left,size,7);
3903           //rFalseIfx.condition ^= 1;
3904
3905           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3906           if(rFalseIfx.condition)
3907             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3908           else
3909             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3910
3911           emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3912           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3913           emitpcode(POC_MOVFW, popGet(AOP(left),1));
3914
3915           while(size > 1)
3916             emitpcode(POC_IORFW, popGet(AOP(left),size--));
3917
3918           if(rFalseIfx.condition) {
3919             emitSKPZ;
3920             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3921
3922           } else {
3923             emitSKPNZ;
3924           }
3925
3926           genSkipc(&rFalseIfx);
3927           emitpLabel(truelbl->key);
3928           if(ifx) ifx->generated = 1;
3929           return;
3930
3931         }
3932
3933         if(size == 1) {
3934
3935           if( (lit & 0xff) == 0) {
3936             /* lower byte is zero */
3937             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3938             i = ((lit >> 8) & 0xff) ^0x80;
3939             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3940             emitpcode(POC_ADDLW, popGetLit( 0x80));
3941             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3942             genSkipc(&rFalseIfx);
3943
3944
3945             if(ifx) ifx->generated = 1;
3946             return;
3947
3948           }
3949         } else {
3950           /* Special cases for signed longs */
3951           if( (lit & 0xffffff) == 0) {
3952             /* lower byte is zero */
3953             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3954             i = ((lit >> 8*3) & 0xff) ^0x80;
3955             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3956             emitpcode(POC_ADDLW, popGetLit( 0x80));
3957             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3958             genSkipc(&rFalseIfx);
3959
3960
3961             if(ifx) ifx->generated = 1;
3962             return;
3963
3964           }
3965
3966         }
3967
3968
3969         if(lit & (0x80 << (size*8))) {
3970           /* lit is negative */
3971           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3972
3973           //genSkipCond(&rFalseIfx,left,size,7);
3974
3975           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3976
3977           if(rFalseIfx.condition)
3978             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3979           else
3980             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3981
3982
3983         } else {
3984           /* lit is positive */
3985           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3986           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3987           if(rFalseIfx.condition)
3988             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3989           else
3990             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3991
3992         }
3993
3994         /*
3995           This works, but is only good for ints.
3996           It also requires a "known zero" register.
3997           emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3998           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3999           emitpcode(POC_RLFW,  popCopyReg(&pc_kzero));
4000           emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
4001           emitpcode(POC_ADDFW, popGet(AOP(left),1));
4002           genSkipc(&rFalseIfx);
4003
4004           emitpLabel(truelbl->key);
4005           if(ifx) ifx->generated = 1;
4006           return;
4007         **/
4008           
4009         /* There are no more special cases, so perform a general compare */
4010   
4011         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4012         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4013
4014         while(size--) {
4015
4016           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4017           emitSKPNZ;
4018           emitpcode(POC_SUBFW, popGet(AOP(left),size));
4019         }
4020         //rFalseIfx.condition ^= 1;
4021         genSkipc(&rFalseIfx);
4022
4023         emitpLabel(truelbl->key);
4024
4025         if(ifx) ifx->generated = 1;
4026         return;
4027
4028
4029       }
4030
4031
4032       /* sign is out of the way. So now do an unsigned compare */
4033       DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4034
4035
4036       /* General case - compare to an unsigned literal on the right.*/
4037
4038       i = (lit >> (size*8)) & 0xff;
4039       emitpcode(POC_MOVLW, popGetLit(i));
4040       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4041       while(size--) {
4042         i = (lit >> (size*8)) & 0xff;
4043
4044         if(i) {
4045           emitpcode(POC_MOVLW, popGetLit(i));
4046           emitSKPNZ;
4047           emitpcode(POC_SUBFW, popGet(AOP(left),size));
4048         } else {
4049           /* this byte of the lit is zero, 
4050            *if it's not the last then OR in the variable */
4051           if(size)
4052             emitpcode(POC_IORFW, popGet(AOP(left),size));
4053         }
4054       }
4055
4056
4057       emitpLabel(lbl->key);
4058       //if(emitFinalCheck)
4059       genSkipc(&rFalseIfx);
4060       if(sign)
4061         emitpLabel(truelbl->key);
4062
4063       if(ifx) ifx->generated = 1;
4064       return;
4065
4066
4067     }
4068 #endif  // _swapp
4069
4070     if(AOP_TYPE(left) == AOP_LIT) {
4071       //symbol *lbl = newiTempLabel(NULL);
4072
4073       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4074
4075
4076       DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4077
4078       /* Special cases */
4079       if((lit == 0) && (sign == 0)){
4080
4081         size--;
4082         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4083         while(size) 
4084           emitpcode(POC_IORFW, popGet(AOP(right),--size));
4085
4086         genSkipz2(&rFalseIfx,0);
4087         if(ifx) ifx->generated = 1;
4088         return;
4089       }
4090
4091       if(size==1) {
4092         /* Special cases */
4093         lit &= 0xff;
4094         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4095           /* degenerate compare can never be true */
4096           if(rFalseIfx.condition == 0)
4097             emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4098
4099           if(ifx) ifx->generated = 1;
4100           return;
4101         }
4102
4103         if(sign) {
4104           /* signed comparisons to a literal byte */
4105
4106           int lp1 = (lit+1) & 0xff;
4107
4108           DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4109           switch (lp1) {
4110           case 0:
4111             rFalseIfx.condition ^= 1;
4112             genSkipCond(&rFalseIfx,right,0,7);
4113             break;
4114           case 0x7f:
4115             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4116             emitpcode(POC_XORLW, popGetLit(0x7f));
4117             genSkipz2(&rFalseIfx,1);
4118             break;
4119           default:
4120             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4121             emitpcode(POC_ADDLW, popGetLit(0x80));
4122             emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4123             rFalseIfx.condition ^= 1;
4124             genSkipc(&rFalseIfx);
4125             break;
4126           }
4127           if(ifx) ifx->generated = 1;
4128         } else {
4129           /* unsigned comparisons to a literal byte */
4130
4131           switch(lit & 0xff ) {
4132           case 0:
4133             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4134             genSkipz2(&rFalseIfx,0);
4135             if(ifx) ifx->generated = 1;
4136             break;
4137           case 0x7f:
4138             rFalseIfx.condition ^= 1;
4139             genSkipCond(&rFalseIfx,right,0,7);
4140             if(ifx) ifx->generated = 1;
4141             break;
4142
4143           default:
4144             emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4145             emitpcode(POC_SUBFW, popGet(AOP(right),0));
4146             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4147             rFalseIfx.condition ^= 1;
4148             if (AOP_TYPE(result) == AOP_CRY) {
4149               genSkipc(&rFalseIfx);
4150               if(ifx) ifx->generated = 1;
4151             } else {
4152               DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4153               emitpcode(POC_CLRF, popGet(AOP(result),0));
4154               emitpcode(POC_RLF, popGet(AOP(result),0));
4155               emitpcode(POC_MOVLW, popGetLit(0x01));
4156               emitpcode(POC_XORWF, popGet(AOP(result),0));
4157             }         
4158             break;
4159           }
4160         }
4161
4162         //goto check_carry;
4163         return;
4164
4165       } else {
4166
4167         /* Size is greater than 1 */
4168
4169         if(sign) {
4170           int lp1 = lit+1;
4171
4172           size--;
4173
4174           if(lp1 == 0) {
4175             /* this means lit = 0xffffffff, or -1 */
4176
4177
4178             DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4179             rFalseIfx.condition ^= 1;
4180             genSkipCond(&rFalseIfx,right,size,7);
4181             if(ifx) ifx->generated = 1;
4182             return;
4183           }
4184
4185           if(lit == 0) {
4186             int s = size;
4187
4188             if(rFalseIfx.condition) {
4189               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4190               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4191             }
4192
4193             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4194             while(size--)
4195               emitpcode(POC_IORFW, popGet(AOP(right),size));
4196
4197
4198             emitSKPZ;
4199             if(rFalseIfx.condition) {
4200               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4201               emitpLabel(truelbl->key);
4202             }else {
4203               rFalseIfx.condition ^= 1;
4204               genSkipCond(&rFalseIfx,right,s,7);
4205             }
4206
4207             if(ifx) ifx->generated = 1;
4208             return;
4209           }
4210
4211           if((size == 1) &&  (0 == (lp1&0xff))) {
4212             /* lower byte of signed word is zero */
4213             DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4214             i = ((lp1 >> 8) & 0xff) ^0x80;
4215             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4216             emitpcode(POC_ADDLW, popGetLit( 0x80));
4217             emitpcode(POC_ADDLW, popGetLit(0x100-i));
4218             rFalseIfx.condition ^= 1;
4219             genSkipc(&rFalseIfx);
4220
4221
4222             if(ifx) ifx->generated = 1;
4223             return;
4224           }
4225
4226           if(lit & (0x80 << (size*8))) {
4227             /* Lit is less than zero */
4228             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4229             //rFalseIfx.condition ^= 1;
4230             //genSkipCond(&rFalseIfx,left,size,7);
4231             //rFalseIfx.condition ^= 1;
4232             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4233             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4234
4235             if(rFalseIfx.condition)
4236               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4237             else
4238               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4239
4240
4241           } else {
4242             /* Lit is greater than or equal to zero */
4243             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4244             //rFalseIfx.condition ^= 1;
4245             //genSkipCond(&rFalseIfx,right,size,7);
4246             //rFalseIfx.condition ^= 1;
4247
4248             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4249             //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4250
4251             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4252             if(rFalseIfx.condition)
4253               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4254             else
4255               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4256
4257           }
4258
4259
4260           emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4261           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4262
4263           while(size--) {
4264
4265             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4266             emitSKPNZ;
4267             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4268           }
4269           rFalseIfx.condition ^= 1;
4270           //rFalseIfx.condition = 1;
4271           genSkipc(&rFalseIfx);
4272
4273           emitpLabel(truelbl->key);
4274
4275           if(ifx) ifx->generated = 1;
4276           return;
4277           // end of if (sign)
4278         } else {
4279
4280           /* compare word or long to an unsigned literal on the right.*/
4281
4282
4283           size--;
4284           if(lit < 0xff) {
4285             DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4286             switch (lit) {
4287             case 0:
4288               break; /* handled above */
4289 /*
4290             case 0xff:
4291               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4292               while(size--)
4293                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4294               genSkipz2(&rFalseIfx,0);
4295               break;
4296 */
4297             default:
4298               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4299               while(--size)
4300                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4301
4302               emitSKPZ;
4303               if(rFalseIfx.condition)
4304                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4305               else
4306                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4307
4308
4309               emitpcode(POC_MOVLW, popGetLit(lit+1));
4310               emitpcode(POC_SUBFW, popGet(AOP(right),0));
4311
4312               rFalseIfx.condition ^= 1;
4313               genSkipc(&rFalseIfx);
4314             }
4315
4316             emitpLabel(truelbl->key);
4317
4318             if(ifx) ifx->generated = 1;
4319             return;
4320           }
4321
4322
4323           lit++;
4324           DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4325           i = (lit >> (size*8)) & 0xff;
4326
4327           emitpcode(POC_MOVLW, popGetLit(i));
4328           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4329
4330           while(size--) {
4331             i = (lit >> (size*8)) & 0xff;
4332
4333             if(i) {
4334               emitpcode(POC_MOVLW, popGetLit(i));
4335               emitSKPNZ;
4336               emitpcode(POC_SUBFW, popGet(AOP(right),size));
4337             } else {
4338               /* this byte of the lit is zero, 
4339                *if it's not the last then OR in the variable */
4340               if(size)
4341                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4342             }
4343           }
4344
4345
4346           emitpLabel(lbl->key);
4347
4348           rFalseIfx.condition ^= 1;
4349           genSkipc(&rFalseIfx);
4350         }
4351
4352         if(sign)
4353           emitpLabel(truelbl->key);
4354         if(ifx) ifx->generated = 1;
4355         return;
4356       }
4357     }
4358     /* Compare two variables */
4359
4360     DEBUGpic14_emitcode(";sign","%d",sign);
4361
4362     size--;
4363     if(sign) {
4364       /* Sigh. thus sucks... */
4365       if(size) {
4366         emitpcode(POC_MOVFW, popGet(AOP(left),size));
4367         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4368         emitpcode(POC_MOVLW, popGetLit(0x80));
4369         emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4370         emitpcode(POC_XORFW, popGet(AOP(right),size));
4371         emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4372       } else {
4373         /* Signed char comparison */
4374         /* Special thanks to Nikolai Golovchenko for this snippet */
4375         emitpcode(POC_MOVFW, popGet(AOP(right),0));
4376         emitpcode(POC_SUBFW, popGet(AOP(left),0));
4377         emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4378         emitpcode(POC_XORFW, popGet(AOP(left),0));
4379         emitpcode(POC_XORFW, popGet(AOP(right),0));
4380         emitpcode(POC_ADDLW, popGetLit(0x80));
4381
4382         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4383         genSkipc(&rFalseIfx);
4384           
4385         if(ifx) ifx->generated = 1;
4386         return;
4387       }
4388
4389     } else {
4390
4391       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4392       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4393     }
4394
4395
4396     /* The rest of the bytes of a multi-byte compare */
4397     while (size) {
4398
4399       emitSKPZ;
4400       emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4401       size--;
4402
4403       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4404       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4405
4406
4407     }
4408
4409     emitpLabel(lbl->key);
4410
4411     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4412     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4413         (AOP_TYPE(result) == AOP_REG)) {
4414       emitpcode(POC_CLRF, popGet(AOP(result),0));
4415       emitpcode(POC_RLF, popGet(AOP(result),0));
4416     } else {
4417       genSkipc(&rFalseIfx);
4418     }         
4419     //genSkipc(&rFalseIfx);
4420     if(ifx) ifx->generated = 1;
4421
4422     return;
4423
4424   }
4425
4426   // check_carry:
4427   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4428     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4429     pic14_outBitC(result);
4430   } else {
4431     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4432     /* if the result is used in the next
4433        ifx conditional branch then generate
4434        code a little differently */
4435     if (ifx )
4436       genIfxJump (ifx,"c");
4437     else
4438       pic14_outBitC(result);
4439     /* leave the result in acc */
4440   }
4441
4442 }
4443
4444 /*-----------------------------------------------------------------*/
4445 /* genCmpGt :- greater than comparison                             */
4446 /*-----------------------------------------------------------------*/
4447 static void genCmpGt (iCode *ic, iCode *ifx)
4448 {
4449     operand *left, *right, *result;
4450     sym_link *letype , *retype;
4451     int sign ;
4452
4453     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4454     left = IC_LEFT(ic);
4455     right= IC_RIGHT(ic);
4456     result = IC_RESULT(ic);
4457
4458     letype = getSpec(operandType(left));
4459     retype =getSpec(operandType(right));
4460     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4461     /* assign the amsops */
4462     aopOp (left,ic,FALSE);
4463     aopOp (right,ic,FALSE);
4464     aopOp (result,ic,TRUE);
4465
4466     genCmp(right, left, result, ifx, sign);
4467
4468     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4469     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4470     freeAsmop(result,NULL,ic,TRUE); 
4471 }
4472
4473 /*-----------------------------------------------------------------*/
4474 /* genCmpLt - less than comparisons                                */
4475 /*-----------------------------------------------------------------*/
4476 static void genCmpLt (iCode *ic, iCode *ifx)
4477 {
4478     operand *left, *right, *result;
4479     sym_link *letype , *retype;
4480     int sign ;
4481
4482     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4483     left = IC_LEFT(ic);
4484     right= IC_RIGHT(ic);
4485     result = IC_RESULT(ic);
4486
4487     letype = getSpec(operandType(left));
4488     retype =getSpec(operandType(right));
4489     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4490
4491     /* assign the amsops */
4492     aopOp (left,ic,FALSE);
4493     aopOp (right,ic,FALSE);
4494     aopOp (result,ic,TRUE);
4495
4496     genCmp(left, right, result, ifx, sign);
4497
4498     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4499     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4500     freeAsmop(result,NULL,ic,TRUE); 
4501 }
4502
4503 /*-----------------------------------------------------------------*/
4504 /* genc16bit2lit - compare a 16 bit value to a literal             */
4505 /*-----------------------------------------------------------------*/
4506 static void genc16bit2lit(operand *op, int lit, int offset)
4507 {
4508   int i;
4509
4510   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4511   if( (lit&0xff) == 0) 
4512     i=1;
4513   else
4514     i=0;
4515
4516   switch( BYTEofLONG(lit,i)) { 
4517   case 0:
4518     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4519     break;
4520   case 1:
4521     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4522     break;
4523   case 0xff:
4524     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4525     break;
4526   default:
4527     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4528     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4529   }
4530
4531   i ^= 1;
4532
4533   switch( BYTEofLONG(lit,i)) { 
4534   case 0:
4535     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4536     break;
4537   case 1:
4538     emitSKPNZ;
4539     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4540     break;
4541   case 0xff:
4542     emitSKPNZ;
4543     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4544     break;
4545   default:
4546     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4547     emitSKPNZ;
4548     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4549
4550   }
4551
4552 }
4553
4554 /*-----------------------------------------------------------------*/
4555 /* gencjneshort - compare and jump if not equal                    */
4556 /*-----------------------------------------------------------------*/
4557 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4558 {
4559   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4560   int offset = 0;
4561   int res_offset = 0;  /* the result may be a different size then left or right */
4562   int res_size = AOP_SIZE(result);
4563   resolvedIfx rIfx;
4564   symbol *lbl;
4565
4566   unsigned long lit = 0L;
4567   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4568   DEBUGpic14_AopType(__LINE__,left,right,result);
4569   if(result)
4570     DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4571   resolveIfx(&rIfx,ifx);
4572   lbl =  newiTempLabel(NULL);
4573
4574
4575   /* if the left side is a literal or 
4576      if the right is in a pointer register and left 
4577      is not */
4578   if ((AOP_TYPE(left) == AOP_LIT) || 
4579       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4580     operand *t = right;
4581     right = left;
4582     left = t;
4583   }
4584   if(AOP_TYPE(right) == AOP_LIT)
4585     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4586
4587   /* if the right side is a literal then anything goes */
4588   if (AOP_TYPE(right) == AOP_LIT &&
4589       AOP_TYPE(left) != AOP_DIR ) {
4590     switch(size) {
4591     case 2:
4592       genc16bit2lit(left, lit, 0);
4593       emitSKPNZ;
4594       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4595       break;
4596     default:
4597       while (size--) {
4598         if(lit & 0xff) {
4599           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4600           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4601         } else {
4602           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4603         }
4604
4605         emitSKPNZ;
4606         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4607         offset++;
4608         if(res_offset < res_size-1)
4609           res_offset++;
4610         lit >>= 8;
4611       }
4612       break;
4613     }
4614   }
4615
4616   /* if the right side is in a register or in direct space or
4617      if the left is a pointer register & right is not */    
4618   else if (AOP_TYPE(right) == AOP_REG ||
4619            AOP_TYPE(right) == AOP_DIR || 
4620            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4621            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4622     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4623     int lbl_key = lbl->key;
4624
4625     if(result) {
4626       emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4627       //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4628     }else {
4629       DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4630       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4631               __FUNCTION__,__LINE__);
4632       return;
4633     }
4634
4635 /*     switch(size) { */
4636 /*     case 2: */
4637 /*       genc16bit2lit(left, lit, 0); */
4638 /*       emitSKPNZ; */
4639 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4640 /*       break; */
4641 /*     default: */
4642     while (size--) {
4643       int emit_skip=1;
4644       if((AOP_TYPE(left) == AOP_DIR) && 
4645          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4646
4647         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4648         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4649
4650       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4651             
4652         switch (lit & 0xff) {
4653         case 0:
4654           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4655           break;
4656         case 1:
4657           emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4658           emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4659           //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4660           emit_skip=0;
4661           break;
4662         case 0xff:
4663           emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4664           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4665           //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4666           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4667           emit_skip=0;
4668           break;
4669         default:
4670           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4671           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4672         }
4673         lit >>= 8;
4674
4675       } else {
4676         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4677       }
4678       if(emit_skip) {
4679         if(AOP_TYPE(result) == AOP_CRY) {
4680           pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4681           if(rIfx.condition)
4682             emitSKPNZ;
4683           else
4684             emitSKPZ;
4685           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4686         } else {
4687           /* fix me. probably need to check result size too */
4688           //emitpcode(POC_CLRF,popGet(AOP(result),0));
4689           if(rIfx.condition)
4690             emitSKPZ;
4691           else
4692             emitSKPNZ;
4693           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4694           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4695         }
4696         if(ifx)
4697           ifx->generated=1;
4698       }
4699       emit_skip++;
4700       offset++;
4701       if(res_offset < res_size-1)
4702         res_offset++;
4703     }
4704 /*       break; */
4705 /*     } */
4706   } else if(AOP_TYPE(right) == AOP_REG &&
4707             AOP_TYPE(left) != AOP_DIR){
4708
4709     while(size--) {
4710       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4711       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4712       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4713       if(rIfx.condition)
4714         emitSKPNZ;
4715       else
4716         emitSKPZ;
4717       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4718       offset++;
4719       if(res_offset < res_size-1)
4720         res_offset++;
4721     }
4722       
4723   }else{
4724     /* right is a pointer reg need both a & b */
4725     while(size--) {
4726       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4727       if(strcmp(l,"b"))
4728         pic14_emitcode("mov","b,%s",l);
4729       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4730       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4731       offset++;
4732     }
4733   }
4734
4735   emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4736   if(!rIfx.condition)
4737     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4738
4739   emitpLabel(lbl->key);
4740
4741   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4742
4743   if(ifx)
4744     ifx->generated = 1;
4745 }
4746
4747 #if 0
4748 /*-----------------------------------------------------------------*/
4749 /* gencjne - compare and jump if not equal                         */
4750 /*-----------------------------------------------------------------*/
4751 static void gencjne(operand *left, operand *right, iCode *ifx)
4752 {
4753     symbol *tlbl  = newiTempLabel(NULL);
4754
4755     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4756     gencjneshort(left, right, lbl);
4757
4758     pic14_emitcode("mov","a,%s",one);
4759     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4760     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4761     pic14_emitcode("clr","a");
4762     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4763
4764     emitpLabel(lbl->key);
4765     emitpLabel(tlbl->key);
4766
4767 }
4768 #endif
4769
4770 /*-----------------------------------------------------------------*/
4771 /* genCmpEq - generates code for equal to                          */
4772 /*-----------------------------------------------------------------*/
4773 static void genCmpEq (iCode *ic, iCode *ifx)
4774 {
4775     operand *left, *right, *result;
4776     unsigned long lit = 0L;
4777     int size,offset=0;
4778
4779     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4780
4781     if(ifx)
4782       DEBUGpic14_emitcode ("; ifx is non-null","");
4783     else
4784       DEBUGpic14_emitcode ("; ifx is null","");
4785
4786     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4787     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4788     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4789
4790     size = max(AOP_SIZE(left),AOP_SIZE(right));
4791
4792     DEBUGpic14_AopType(__LINE__,left,right,result);
4793
4794     /* if literal, literal on the right or 
4795     if the right is in a pointer register and left 
4796     is not */
4797     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4798         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4799       operand *tmp = right ;
4800       right = left;
4801       left = tmp;
4802     }
4803
4804
4805     if(ifx && !AOP_SIZE(result)){
4806         symbol *tlbl;
4807         /* if they are both bit variables */
4808         if (AOP_TYPE(left) == AOP_CRY &&
4809             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4810             if(AOP_TYPE(right) == AOP_LIT){
4811                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4812                 if(lit == 0L){
4813                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4814                     pic14_emitcode("cpl","c");
4815                 } else if(lit == 1L) {
4816                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4817                 } else {
4818                     pic14_emitcode("clr","c");
4819                 }
4820                 /* AOP_TYPE(right) == AOP_CRY */
4821             } else {
4822                 symbol *lbl = newiTempLabel(NULL);
4823                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4824                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4825                 pic14_emitcode("cpl","c");
4826                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4827             }
4828             /* if true label then we jump if condition
4829             supplied is true */
4830             tlbl = newiTempLabel(NULL);
4831             if ( IC_TRUE(ifx) ) {
4832                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4833                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4834             } else {
4835                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4836                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4837             }
4838             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4839
4840             {
4841               /* left and right are both bit variables, result is carry */
4842               resolvedIfx rIfx;
4843               
4844               resolveIfx(&rIfx,ifx);
4845
4846               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4847               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4848               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4849               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4850               genSkipz2(&rIfx,0);
4851             }
4852         } else {
4853
4854           /* They're not both bit variables. Is the right a literal? */
4855           if(AOP_TYPE(right) == AOP_LIT) {
4856             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4857             
4858             switch(size) {
4859
4860             case 1:
4861               switch(lit & 0xff) {
4862               case 1:
4863                 if ( IC_TRUE(ifx) ) {
4864                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4865                   emitSKPNZ;
4866                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4867                 } else {
4868                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4869                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4870                 }
4871                 break;
4872               case 0xff:
4873                 if ( IC_TRUE(ifx) ) {
4874                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4875                   emitSKPNZ;
4876                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4877                 } else {
4878                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4879                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4880                 }
4881                 break;
4882               default:
4883                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4884                 if(lit)
4885                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4886                 genSkip(ifx,'z');
4887               }
4888
4889
4890               /* end of size == 1 */
4891               break;
4892               
4893             case 2:
4894               genc16bit2lit(left,lit,offset);
4895               genSkip(ifx,'z');
4896               break;
4897               /* end of size == 2 */
4898
4899             default:
4900               /* size is 4 */
4901               if(lit==0) {
4902                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4903                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4904                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4905                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4906
4907               } else {
4908
4909                 /* search for patterns that can be optimized */
4910
4911                 genc16bit2lit(left,lit,0);
4912                 lit >>= 16;
4913                 if(lit) {
4914                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4915                   //genSkip(ifx,'z');
4916                   genc16bit2lit(left,lit,2);
4917                 } else {
4918                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4919                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4920
4921                 }
4922                 
4923               }
4924
4925               genSkip(ifx,'z');
4926             }
4927           
4928             ifx->generated = 1;
4929             goto release ;
4930             
4931
4932           } else if(AOP_TYPE(right) == AOP_CRY ) {
4933             /* we know the left is not a bit, but that the right is */
4934             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4935             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4936                       popGet(AOP(right),offset));
4937             emitpcode(POC_XORLW,popGetLit(1));
4938
4939             /* if the two are equal, then W will be 0 and the Z bit is set
4940              * we could test Z now, or go ahead and check the high order bytes if
4941              * the variable we're comparing is larger than a byte. */
4942
4943             while(--size)
4944               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4945
4946             if ( IC_TRUE(ifx) ) {
4947               emitSKPNZ;
4948               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4949               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4950             } else {
4951               emitSKPZ;
4952               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4953               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4954             }
4955
4956           } else {
4957             /* They're both variables that are larger than bits */
4958             int s = size;
4959
4960             tlbl = newiTempLabel(NULL);
4961
4962             while(size--) {
4963               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4964               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4965
4966               if ( IC_TRUE(ifx) ) {
4967                 if(size) {
4968                   emitSKPZ;
4969                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4970                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4971                 } else {
4972                   emitSKPNZ;
4973                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4974                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4975                 }
4976               } else {
4977                 emitSKPZ;
4978                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4979                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4980               }
4981               offset++;
4982             }
4983             if(s>1 && IC_TRUE(ifx)) {
4984               emitpLabel(tlbl->key);
4985               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4986             }
4987           }
4988         }
4989         /* mark the icode as generated */
4990         ifx->generated = 1;
4991         goto release ;
4992     }
4993
4994     /* if they are both bit variables */
4995     if (AOP_TYPE(left) == AOP_CRY &&
4996         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4997         if(AOP_TYPE(right) == AOP_LIT){
4998             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4999             if(lit == 0L){
5000                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5001                 pic14_emitcode("cpl","c");
5002             } else if(lit == 1L) {
5003                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5004             } else {
5005                 pic14_emitcode("clr","c");
5006             }
5007             /* AOP_TYPE(right) == AOP_CRY */
5008         } else {
5009             symbol *lbl = newiTempLabel(NULL);
5010             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5011             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5012             pic14_emitcode("cpl","c");
5013             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5014         }
5015         /* c = 1 if egal */
5016         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5017             pic14_outBitC(result);
5018             goto release ;
5019         }
5020         if (ifx) {
5021             genIfxJump (ifx,"c");
5022             goto release ;
5023         }
5024         /* if the result is used in an arithmetic operation
5025         then put the result in place */
5026         pic14_outBitC(result);
5027     } else {
5028       
5029       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5030       gencjne(left,right,result,ifx);
5031 /*
5032       if(ifx) 
5033         gencjne(left,right,newiTempLabel(NULL));
5034       else {
5035         if(IC_TRUE(ifx)->key)
5036           gencjne(left,right,IC_TRUE(ifx)->key);
5037         else
5038           gencjne(left,right,IC_FALSE(ifx)->key);
5039         ifx->generated = 1;
5040         goto release ;
5041       }
5042       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5043         aopPut(AOP(result),"a",0);
5044         goto release ;
5045       }
5046
5047       if (ifx) {
5048         genIfxJump (ifx,"a");
5049         goto release ;
5050       }
5051 */
5052       /* if the result is used in an arithmetic operation
5053          then put the result in place */
5054 /*
5055       if (AOP_TYPE(result) != AOP_CRY) 
5056         pic14_outAcc(result);
5057 */
5058       /* leave the result in acc */
5059     }
5060
5061 release:
5062     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5063     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5064     freeAsmop(result,NULL,ic,TRUE);
5065 }
5066
5067 /*-----------------------------------------------------------------*/
5068 /* ifxForOp - returns the icode containing the ifx for operand     */
5069 /*-----------------------------------------------------------------*/
5070 static iCode *ifxForOp ( operand *op, iCode *ic )
5071 {
5072     /* if true symbol then needs to be assigned */
5073     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5074     if (IS_TRUE_SYMOP(op))
5075         return NULL ;
5076
5077     /* if this has register type condition and
5078     the next instruction is ifx with the same operand
5079     and live to of the operand is upto the ifx only then */
5080     if (ic->next &&
5081         ic->next->op == IFX &&
5082         IC_COND(ic->next)->key == op->key &&
5083         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5084         return ic->next;
5085
5086     if (ic->next &&
5087         ic->next->op == IFX &&
5088         IC_COND(ic->next)->key == op->key) {
5089       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5090       return ic->next;
5091     }
5092
5093     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5094     if (ic->next &&
5095         ic->next->op == IFX)
5096       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5097
5098     if (ic->next &&
5099         ic->next->op == IFX &&
5100         IC_COND(ic->next)->key == op->key) {
5101       DEBUGpic14_emitcode ("; "," key is okay");
5102       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5103                            OP_SYMBOL(op)->liveTo,
5104                            ic->next->seq);
5105     }
5106
5107
5108     return NULL;
5109 }
5110 /*-----------------------------------------------------------------*/
5111 /* genAndOp - for && operation                                     */
5112 /*-----------------------------------------------------------------*/
5113 static void genAndOp (iCode *ic)
5114 {
5115     operand *left,*right, *result;
5116 /*     symbol *tlbl; */
5117
5118     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5119     /* note here that && operations that are in an
5120     if statement are taken away by backPatchLabels
5121     only those used in arthmetic operations remain */
5122     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5123     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5124     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5125
5126     DEBUGpic14_AopType(__LINE__,left,right,result);
5127
5128     emitpcode(POC_MOVFW,popGet(AOP(left),0));
5129     emitpcode(POC_ANDFW,popGet(AOP(right),0));
5130     emitpcode(POC_MOVWF,popGet(AOP(result),0));
5131
5132     /* if both are bit variables */
5133 /*     if (AOP_TYPE(left) == AOP_CRY && */
5134 /*         AOP_TYPE(right) == AOP_CRY ) { */
5135 /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5136 /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5137 /*         pic14_outBitC(result); */
5138 /*     } else { */
5139 /*         tlbl = newiTempLabel(NULL); */
5140 /*         pic14_toBoolean(left);     */
5141 /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5142 /*         pic14_toBoolean(right); */
5143 /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5144 /*         pic14_outBitAcc(result); */
5145 /*     } */
5146
5147     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5148     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5149     freeAsmop(result,NULL,ic,TRUE);
5150 }
5151
5152
5153 /*-----------------------------------------------------------------*/
5154 /* genOrOp - for || operation                                      */
5155 /*-----------------------------------------------------------------*/
5156 /*
5157   tsd pic port -
5158   modified this code, but it doesn't appear to ever get called
5159 */
5160
5161 static void genOrOp (iCode *ic)
5162 {
5163     operand *left,*right, *result;
5164     symbol *tlbl;
5165
5166     /* note here that || operations that are in an
5167     if statement are taken away by backPatchLabels
5168     only those used in arthmetic operations remain */
5169     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5170     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5171     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5172     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5173
5174     DEBUGpic14_AopType(__LINE__,left,right,result);
5175
5176     /* if both are bit variables */
5177     if (AOP_TYPE(left) == AOP_CRY &&
5178         AOP_TYPE(right) == AOP_CRY ) {
5179       pic14_emitcode("clrc","");
5180       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5181                AOP(left)->aopu.aop_dir,
5182                AOP(left)->aopu.aop_dir);
5183       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5184                AOP(right)->aopu.aop_dir,
5185                AOP(right)->aopu.aop_dir);
5186       pic14_emitcode("setc","");
5187
5188     } else {
5189         tlbl = newiTempLabel(NULL);
5190         pic14_toBoolean(left);
5191         emitSKPZ;
5192         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5193         pic14_toBoolean(right);
5194         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5195
5196         pic14_outBitAcc(result);
5197     }
5198
5199     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5200     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5201     freeAsmop(result,NULL,ic,TRUE);            
5202 }
5203
5204 /*-----------------------------------------------------------------*/
5205 /* isLiteralBit - test if lit == 2^n                               */
5206 /*-----------------------------------------------------------------*/
5207 static int isLiteralBit(unsigned long lit)
5208 {
5209     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5210     0x100L,0x200L,0x400L,0x800L,
5211     0x1000L,0x2000L,0x4000L,0x8000L,
5212     0x10000L,0x20000L,0x40000L,0x80000L,
5213     0x100000L,0x200000L,0x400000L,0x800000L,
5214     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5215     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5216     int idx;
5217     
5218     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5219     for(idx = 0; idx < 32; idx++)
5220         if(lit == pw[idx])
5221             return idx+1;
5222     return 0;
5223 }
5224
5225 /*-----------------------------------------------------------------*/
5226 /* continueIfTrue -                                                */
5227 /*-----------------------------------------------------------------*/
5228 static void continueIfTrue (iCode *ic)
5229 {
5230     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5231     if(IC_TRUE(ic))
5232         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5233     ic->generated = 1;
5234 }
5235
5236 /*-----------------------------------------------------------------*/
5237 /* jmpIfTrue -                                                     */
5238 /*-----------------------------------------------------------------*/
5239 static void jumpIfTrue (iCode *ic)
5240 {
5241     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5242     if(!IC_TRUE(ic))
5243         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5244     ic->generated = 1;
5245 }
5246
5247 /*-----------------------------------------------------------------*/
5248 /* jmpTrueOrFalse -                                                */
5249 /*-----------------------------------------------------------------*/
5250 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5251 {
5252     // ugly but optimized by peephole
5253     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5254     if(IC_TRUE(ic)){
5255         symbol *nlbl = newiTempLabel(NULL);
5256         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5257         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5258         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5259         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5260     }
5261     else{
5262         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5263         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5264     }
5265     ic->generated = 1;
5266 }
5267
5268 /*-----------------------------------------------------------------*/
5269 /* genAnd  - code for and                                          */
5270 /*-----------------------------------------------------------------*/
5271 static void genAnd (iCode *ic, iCode *ifx)
5272 {
5273   operand *left, *right, *result;
5274   int size, offset=0;  
5275   unsigned long lit = 0L;
5276   int bytelit = 0;
5277   resolvedIfx rIfx;
5278
5279
5280   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5281   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5282   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5283   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5284
5285   resolveIfx(&rIfx,ifx);
5286
5287   /* if left is a literal & right is not then exchange them */
5288   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5289       AOP_NEEDSACC(left)) {
5290     operand *tmp = right ;
5291     right = left;
5292     left = tmp;
5293   }
5294
5295   /* if result = right then exchange them */
5296   if(pic14_sameRegs(AOP(result),AOP(right))){
5297     operand *tmp = right ;
5298     right = left;
5299     left = tmp;
5300   }
5301
5302   /* if right is bit then exchange them */
5303   if (AOP_TYPE(right) == AOP_CRY &&
5304       AOP_TYPE(left) != AOP_CRY){
5305     operand *tmp = right ;
5306     right = left;
5307     left = tmp;
5308   }
5309   if(AOP_TYPE(right) == AOP_LIT)
5310     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5311
5312   size = AOP_SIZE(result);
5313
5314   DEBUGpic14_AopType(__LINE__,left,right,result);
5315
5316   // if(bit & yy)
5317   // result = bit & yy;
5318   if (AOP_TYPE(left) == AOP_CRY){
5319     // c = bit & literal;
5320     if(AOP_TYPE(right) == AOP_LIT){
5321       if(lit & 1) {
5322         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5323           // no change
5324           goto release;
5325         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5326       } else {
5327         // bit(result) = 0;
5328         if(size && (AOP_TYPE(result) == AOP_CRY)){
5329           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5330           goto release;
5331         }
5332         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5333           jumpIfTrue(ifx);
5334           goto release;
5335         }
5336         pic14_emitcode("clr","c");
5337       }
5338     } else {
5339       if (AOP_TYPE(right) == AOP_CRY){
5340         // c = bit & bit;
5341         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5342         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5343       } else {
5344         // c = bit & val;
5345         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5346         // c = lsb
5347         pic14_emitcode("rrc","a");
5348         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5349       }
5350     }
5351     // bit = c
5352     // val = c
5353     if(size)
5354       pic14_outBitC(result);
5355     // if(bit & ...)
5356     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5357       genIfxJump(ifx, "c");           
5358     goto release ;
5359   }
5360
5361   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5362   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5363   if((AOP_TYPE(right) == AOP_LIT) &&
5364      (AOP_TYPE(result) == AOP_CRY) &&
5365      (AOP_TYPE(left) != AOP_CRY)){
5366     int posbit = isLiteralBit(lit);
5367     /* left &  2^n */
5368     if(posbit){
5369       posbit--;
5370       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5371       // bit = left & 2^n
5372       if(size)
5373         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5374       // if(left &  2^n)
5375       else{
5376         if(ifx){
5377 /*
5378           if(IC_TRUE(ifx)) {
5379             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5380             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
5381           } else {
5382             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5383             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
5384           }
5385 */
5386           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5387                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5388           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5389           
5390           ifx->generated = 1;
5391         }
5392         goto release;
5393       }
5394     } else {
5395       symbol *tlbl = newiTempLabel(NULL);
5396       int sizel = AOP_SIZE(left);
5397       if(size)
5398         pic14_emitcode("setb","c");
5399       while(sizel--){
5400         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5401           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5402           // byte ==  2^n ?
5403           if((posbit = isLiteralBit(bytelit)) != 0)
5404             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5405           else{
5406             if(bytelit != 0x0FFL)
5407               pic14_emitcode("anl","a,%s",
5408                              aopGet(AOP(right),offset,FALSE,TRUE));
5409             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5410           }
5411         }
5412         offset++;
5413       }
5414       // bit = left & literal
5415       if(size){
5416         pic14_emitcode("clr","c");
5417         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5418       }
5419       // if(left & literal)
5420       else{
5421         if(ifx)
5422           jmpTrueOrFalse(ifx, tlbl);
5423         goto release ;
5424       }
5425     }
5426     pic14_outBitC(result);
5427     goto release ;
5428   }
5429
5430   /* if left is same as result */
5431   if(pic14_sameRegs(AOP(result),AOP(left))){
5432     int know_W = -1;
5433     for(;size--; offset++,lit>>=8) {
5434       if(AOP_TYPE(right) == AOP_LIT){
5435         switch(lit & 0xff) {
5436         case 0x00:
5437           /*  and'ing with 0 has clears the result */
5438           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5439           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5440           break;
5441         case 0xff:
5442           /* and'ing with 0xff is a nop when the result and left are the same */
5443           break;
5444
5445         default:
5446           {
5447             int p = my_powof2( (~lit) & 0xff );
5448             if(p>=0) {
5449               /* only one bit is set in the literal, so use a bcf instruction */
5450               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5451               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5452
5453             } else {
5454               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5455               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5456               if(know_W != (int)(lit&0xff))
5457                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5458               know_W = lit &0xff;
5459               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5460             }
5461           }    
5462         }
5463       } else {
5464         if (AOP_TYPE(left) == AOP_ACC) {
5465           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5466         } else {                    
5467           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5468           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5469
5470         }
5471       }
5472     }
5473
5474   } else {
5475     // left & result in different registers
5476     if(AOP_TYPE(result) == AOP_CRY){
5477       // result = bit
5478       // if(size), result in bit
5479       // if(!size && ifx), conditional oper: if(left & right)
5480       symbol *tlbl = newiTempLabel(NULL);
5481       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5482       if(size)
5483         pic14_emitcode("setb","c");
5484       while(sizer--){
5485         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5486         pic14_emitcode("anl","a,%s",
5487                        aopGet(AOP(left),offset,FALSE,FALSE));
5488         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5489         offset++;
5490       }
5491       if(size){
5492         CLRC;
5493         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5494         pic14_outBitC(result);
5495       } else if(ifx)
5496         jmpTrueOrFalse(ifx, tlbl);
5497     } else {
5498       for(;(size--);offset++) {
5499         // normal case
5500         // result = left & right
5501         if(AOP_TYPE(right) == AOP_LIT){
5502           int t = (lit >> (offset*8)) & 0x0FFL;
5503           switch(t) { 
5504           case 0x00:
5505             pic14_emitcode("clrf","%s",
5506                            aopGet(AOP(result),offset,FALSE,FALSE));
5507             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5508             break;
5509           case 0xff:
5510             if(AOP_TYPE(left) != AOP_ACC) {
5511               pic14_emitcode("movf","%s,w",
5512                              aopGet(AOP(left),offset,FALSE,FALSE));
5513               pic14_emitcode("movwf","%s",
5514                              aopGet(AOP(result),offset,FALSE,FALSE));
5515               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5516             }
5517             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5518             break;
5519           default:
5520             if(AOP_TYPE(left) == AOP_ACC) {
5521               emitpcode(POC_ANDLW, popGetLit(t));
5522             } else {
5523               pic14_emitcode("movlw","0x%x",t);
5524               pic14_emitcode("andwf","%s,w",
5525                              aopGet(AOP(left),offset,FALSE,FALSE));
5526               pic14_emitcode("movwf","%s",
5527                              aopGet(AOP(result),offset,FALSE,FALSE));
5528               
5529               emitpcode(POC_MOVLW, popGetLit(t));
5530               emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5531             }
5532             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5533           }
5534           continue;
5535         }
5536
5537         if (AOP_TYPE(left) == AOP_ACC) {
5538           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5539           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5540         } else {
5541           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5542           pic14_emitcode("andwf","%s,w",
5543                          aopGet(AOP(left),offset,FALSE,FALSE));
5544           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5545           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5546         }
5547         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5548         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5549       }
5550     }
5551   }
5552
5553   release :
5554     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5555   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5556   freeAsmop(result,NULL,ic,TRUE);     
5557 }
5558
5559 /*-----------------------------------------------------------------*/
5560 /* genOr  - code for or                                            */
5561 /*-----------------------------------------------------------------*/
5562 static void genOr (iCode *ic, iCode *ifx)
5563 {
5564     operand *left, *right, *result;
5565     int size, offset=0;
5566     unsigned long lit = 0L;
5567
5568     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5569
5570     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5571     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5572     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5573
5574     DEBUGpic14_AopType(__LINE__,left,right,result);
5575
5576     /* if left is a literal & right is not then exchange them */
5577     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5578         AOP_NEEDSACC(left)) {
5579         operand *tmp = right ;
5580         right = left;
5581         left = tmp;
5582     }
5583
5584     /* if result = right then exchange them */
5585     if(pic14_sameRegs(AOP(result),AOP(right))){
5586         operand *tmp = right ;
5587         right = left;
5588         left = tmp;
5589     }
5590
5591     /* if right is bit then exchange them */
5592     if (AOP_TYPE(right) == AOP_CRY &&
5593         AOP_TYPE(left) != AOP_CRY){
5594         operand *tmp = right ;
5595         right = left;
5596         left = tmp;
5597     }
5598
5599     DEBUGpic14_AopType(__LINE__,left,right,result);
5600
5601     if(AOP_TYPE(right) == AOP_LIT)
5602         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5603
5604     size = AOP_SIZE(result);
5605
5606     // if(bit | yy)
5607     // xx = bit | yy;
5608     if (AOP_TYPE(left) == AOP_CRY){
5609         if(AOP_TYPE(right) == AOP_LIT){
5610             // c = bit & literal;
5611             if(lit){
5612                 // lit != 0 => result = 1
5613                 if(AOP_TYPE(result) == AOP_CRY){
5614                   if(size)
5615                     emitpcode(POC_BSF, popGet(AOP(result),0));
5616                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5617                   //     AOP(result)->aopu.aop_dir,
5618                   //     AOP(result)->aopu.aop_dir);
5619                     else if(ifx)
5620                         continueIfTrue(ifx);
5621                     goto release;
5622                 }
5623             } else {
5624                 // lit == 0 => result = left
5625                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5626                     goto release;
5627                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5628             }
5629         } else {
5630             if (AOP_TYPE(right) == AOP_CRY){
5631               if(pic14_sameRegs(AOP(result),AOP(left))){
5632                 // c = bit | bit;
5633                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5634                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5635                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5636
5637                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5638                          AOP(result)->aopu.aop_dir,
5639                          AOP(result)->aopu.aop_dir);
5640                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5641                          AOP(right)->aopu.aop_dir,
5642                          AOP(right)->aopu.aop_dir);
5643                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5644                          AOP(result)->aopu.aop_dir,
5645                          AOP(result)->aopu.aop_dir);
5646               } else {
5647                 if( AOP_TYPE(result) == AOP_ACC) {
5648                   emitpcode(POC_MOVLW, popGetLit(0));
5649                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5650                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5651                   emitpcode(POC_MOVLW, popGetLit(1));
5652
5653                 } else {
5654
5655                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5656                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5657                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5658                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5659
5660                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5661                                  AOP(result)->aopu.aop_dir,
5662                                  AOP(result)->aopu.aop_dir);
5663                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5664                                  AOP(right)->aopu.aop_dir,
5665                                  AOP(right)->aopu.aop_dir);
5666                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5667                                  AOP(left)->aopu.aop_dir,
5668                                  AOP(left)->aopu.aop_dir);
5669                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5670                                  AOP(result)->aopu.aop_dir,
5671                                  AOP(result)->aopu.aop_dir);
5672                 }
5673               }
5674             } else {
5675                 // c = bit | val;
5676                 symbol *tlbl = newiTempLabel(NULL);
5677                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5678
5679
5680                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5681                 if( AOP_TYPE(right) == AOP_ACC) {
5682                   emitpcode(POC_IORLW, popGetLit(0));
5683                   emitSKPNZ;
5684                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5685                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5686                 }
5687
5688
5689
5690                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5691                     pic14_emitcode(";XXX setb","c");
5692                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5693                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5694                 pic14_toBoolean(right);
5695                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5696                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5697                     jmpTrueOrFalse(ifx, tlbl);
5698                     goto release;
5699                 } else {
5700                     CLRC;
5701                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5702                 }
5703             }
5704         }
5705         // bit = c
5706         // val = c
5707         if(size)
5708             pic14_outBitC(result);
5709         // if(bit | ...)
5710         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5711             genIfxJump(ifx, "c");           
5712         goto release ;
5713     }
5714
5715     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5716     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5717     if((AOP_TYPE(right) == AOP_LIT) &&
5718        (AOP_TYPE(result) == AOP_CRY) &&
5719        (AOP_TYPE(left) != AOP_CRY)){
5720         if(lit){
5721           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5722             // result = 1
5723             if(size)
5724                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5725             else 
5726                 continueIfTrue(ifx);
5727             goto release;
5728         } else {
5729           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5730             // lit = 0, result = boolean(left)
5731             if(size)
5732                 pic14_emitcode(";XXX setb","c");
5733             pic14_toBoolean(right);
5734             if(size){
5735                 symbol *tlbl = newiTempLabel(NULL);
5736                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5737                 CLRC;
5738                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5739             } else {
5740                 genIfxJump (ifx,"a");
5741                 goto release;
5742             }
5743         }
5744         pic14_outBitC(result);
5745         goto release ;
5746     }
5747
5748     /* if left is same as result */
5749     if(pic14_sameRegs(AOP(result),AOP(left))){
5750       int know_W = -1;
5751       for(;size--; offset++,lit>>=8) {
5752         if(AOP_TYPE(right) == AOP_LIT){
5753           if((lit & 0xff) == 0)
5754             /*  or'ing with 0 has no effect */
5755             continue;
5756           else {
5757             int p = my_powof2(lit & 0xff);
5758             if(p>=0) {
5759               /* only one bit is set in the literal, so use a bsf instruction */
5760               emitpcode(POC_BSF,
5761                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5762             } else {
5763               if(know_W != (int)(lit & 0xff))
5764                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5765               know_W = lit & 0xff;
5766               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5767             }
5768                     
5769           }
5770         } else {
5771           if (AOP_TYPE(left) == AOP_ACC) {
5772             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5773             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5774           } else {                  
5775             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5776             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5777
5778             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5779             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5780
5781           }
5782         }
5783       }
5784     } else {
5785         // left & result in different registers
5786         if(AOP_TYPE(result) == AOP_CRY){
5787             // result = bit
5788             // if(size), result in bit
5789             // if(!size && ifx), conditional oper: if(left | right)
5790             symbol *tlbl = newiTempLabel(NULL);
5791             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5792             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5793
5794
5795             if(size)
5796                 pic14_emitcode(";XXX setb","c");
5797             while(sizer--){
5798                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5799                 pic14_emitcode(";XXX orl","a,%s",
5800                          aopGet(AOP(left),offset,FALSE,FALSE));
5801                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5802                 offset++;
5803             }
5804             if(size){
5805                 CLRC;
5806                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5807                 pic14_outBitC(result);
5808             } else if(ifx)
5809                 jmpTrueOrFalse(ifx, tlbl);
5810         } else for(;(size--);offset++){
5811           // normal case
5812           // result = left & right
5813           if(AOP_TYPE(right) == AOP_LIT){
5814             int t = (lit >> (offset*8)) & 0x0FFL;
5815             switch(t) { 
5816             case 0x00:
5817               if (AOP_TYPE(left) != AOP_ACC) {
5818                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5819               }
5820               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5821
5822               break;
5823             default:
5824               if (AOP_TYPE(left) == AOP_ACC) {
5825                 emitpcode(POC_IORLW,  popGetLit(t));
5826               } else {
5827                 emitpcode(POC_MOVLW,  popGetLit(t));
5828                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5829               }
5830               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));              
5831             }
5832             continue;
5833           }
5834
5835           // faster than result <- left, anl result,right
5836           // and better if result is SFR
5837           if (AOP_TYPE(left) == AOP_ACC) {
5838             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5839             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5840           } else {
5841             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5842             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5843
5844             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5845             pic14_emitcode("iorwf","%s,w",
5846                      aopGet(AOP(left),offset,FALSE,FALSE));
5847           }
5848           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5849           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5850         }
5851     }
5852
5853 release :
5854     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5855     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5856     freeAsmop(result,NULL,ic,TRUE);     
5857 }
5858
5859 /*-----------------------------------------------------------------*/
5860 /* genXor - code for xclusive or                                   */
5861 /*-----------------------------------------------------------------*/
5862 static void genXor (iCode *ic, iCode *ifx)
5863 {
5864   operand *left, *right, *result;
5865   int size, offset=0;
5866   unsigned long lit = 0L;
5867
5868   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5869
5870   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5871   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5872   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5873
5874   /* if left is a literal & right is not ||
5875      if left needs acc & right does not */
5876   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5877       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5878     operand *tmp = right ;
5879     right = left;
5880     left = tmp;
5881   }
5882
5883   /* if result = right then exchange them */
5884   if(pic14_sameRegs(AOP(result),AOP(right))){
5885     operand *tmp = right ;
5886     right = left;
5887     left = tmp;
5888   }
5889
5890   /* if right is bit then exchange them */
5891   if (AOP_TYPE(right) == AOP_CRY &&
5892       AOP_TYPE(left) != AOP_CRY){
5893     operand *tmp = right ;
5894     right = left;
5895     left = tmp;
5896   }
5897   if(AOP_TYPE(right) == AOP_LIT)
5898     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5899
5900   size = AOP_SIZE(result);
5901
5902   // if(bit ^ yy)
5903   // xx = bit ^ yy;
5904   if (AOP_TYPE(left) == AOP_CRY){
5905     if(AOP_TYPE(right) == AOP_LIT){
5906       // c = bit & literal;
5907       if(lit>>1){
5908         // lit>>1  != 0 => result = 1
5909         if(AOP_TYPE(result) == AOP_CRY){
5910           if(size)
5911             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5912             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5913           else if(ifx)
5914             continueIfTrue(ifx);
5915           goto release;
5916         }
5917         pic14_emitcode("setb","c");
5918       } else{
5919         // lit == (0 or 1)
5920         if(lit == 0){
5921           // lit == 0, result = left
5922           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5923             goto release;
5924           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5925         } else{
5926           // lit == 1, result = not(left)
5927           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5928             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5929             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5930             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5931             goto release;
5932           } else {
5933             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5934             pic14_emitcode("cpl","c");
5935           }
5936         }
5937       }
5938
5939     } else {
5940       // right != literal
5941       symbol *tlbl = newiTempLabel(NULL);
5942       if (AOP_TYPE(right) == AOP_CRY){
5943         // c = bit ^ bit;
5944         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5945       }
5946       else{
5947         int sizer = AOP_SIZE(right);
5948         // c = bit ^ val
5949         // if val>>1 != 0, result = 1
5950         pic14_emitcode("setb","c");
5951         while(sizer){
5952           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5953           if(sizer == 1)
5954             // test the msb of the lsb
5955             pic14_emitcode("anl","a,#0xfe");
5956           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5957           sizer--;
5958         }
5959         // val = (0,1)
5960         pic14_emitcode("rrc","a");
5961       }
5962       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5963       pic14_emitcode("cpl","c");
5964       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5965     }
5966     // bit = c
5967     // val = c
5968     if(size)
5969       pic14_outBitC(result);
5970     // if(bit | ...)
5971     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5972       genIfxJump(ifx, "c");           
5973     goto release ;
5974   }
5975
5976   if(pic14_sameRegs(AOP(result),AOP(left))){
5977     /* if left is same as result */
5978     for(;size--; offset++) {
5979       if(AOP_TYPE(right) == AOP_LIT){
5980         int t  = (lit >> (offset*8)) & 0x0FFL;
5981         if(t == 0x00L)
5982           continue;
5983         else
5984           if (IS_AOP_PREG(left)) {
5985             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5986             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5987             aopPut(AOP(result),"a",offset);
5988           } else {
5989             emitpcode(POC_MOVLW, popGetLit(t));
5990             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5991             pic14_emitcode("xrl","%s,%s",
5992                            aopGet(AOP(left),offset,FALSE,TRUE),
5993                            aopGet(AOP(right),offset,FALSE,FALSE));
5994           }
5995       } else {
5996         if (AOP_TYPE(left) == AOP_ACC)
5997           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5998         else {
5999           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6000           emitpcode(POC_XORWF,popGet(AOP(left),offset));
6001 /*
6002           if (IS_AOP_PREG(left)) {
6003             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6004             aopPut(AOP(result),"a",offset);
6005           } else
6006             pic14_emitcode("xrl","%s,a",
6007                            aopGet(AOP(left),offset,FALSE,TRUE));
6008 */
6009         }
6010       }
6011     }
6012   } else {
6013     // left & result in different registers
6014     if(AOP_TYPE(result) == AOP_CRY){
6015       // result = bit
6016       // if(size), result in bit
6017       // if(!size && ifx), conditional oper: if(left ^ right)
6018       symbol *tlbl = newiTempLabel(NULL);
6019       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6020       if(size)
6021         pic14_emitcode("setb","c");
6022       while(sizer--){
6023         if((AOP_TYPE(right) == AOP_LIT) &&
6024            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6025           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6026         } else {
6027           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6028           pic14_emitcode("xrl","a,%s",
6029                          aopGet(AOP(left),offset,FALSE,FALSE));
6030         }
6031         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6032         offset++;
6033       }
6034       if(size){
6035         CLRC;
6036         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6037         pic14_outBitC(result);
6038       } else if(ifx)
6039         jmpTrueOrFalse(ifx, tlbl);
6040     } else for(;(size--);offset++){
6041       // normal case
6042       // result = left & right
6043       if(AOP_TYPE(right) == AOP_LIT){
6044         int t = (lit >> (offset*8)) & 0x0FFL;
6045         switch(t) { 
6046         case 0x00:
6047           if (AOP_TYPE(left) != AOP_ACC) {
6048             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6049           }
6050           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6051           pic14_emitcode("movf","%s,w",
6052                          aopGet(AOP(left),offset,FALSE,FALSE));
6053           pic14_emitcode("movwf","%s",
6054                          aopGet(AOP(result),offset,FALSE,FALSE));
6055           break;
6056         case 0xff:
6057           if (AOP_TYPE(left) == AOP_ACC) {
6058             emitpcode(POC_XORLW, popGetLit(t));
6059           } else {
6060             emitpcode(POC_COMFW,popGet(AOP(left),offset));
6061           }
6062           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6063           break;
6064         default:
6065           if (AOP_TYPE(left) == AOP_ACC) {
6066             emitpcode(POC_XORLW, popGetLit(t));
6067           } else {
6068             emitpcode(POC_MOVLW, popGetLit(t));
6069             emitpcode(POC_XORFW,popGet(AOP(left),offset));
6070           }
6071           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6072           pic14_emitcode("movlw","0x%x",t);
6073           pic14_emitcode("xorwf","%s,w",
6074                          aopGet(AOP(left),offset,FALSE,FALSE));
6075           pic14_emitcode("movwf","%s",
6076                          aopGet(AOP(result),offset,FALSE,FALSE));
6077
6078         }
6079         continue;
6080       }
6081
6082       // faster than result <- left, anl result,right
6083       // and better if result is SFR
6084       if (AOP_TYPE(left) == AOP_ACC) {
6085         emitpcode(POC_XORFW,popGet(AOP(right),offset));
6086         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6087       } else {
6088         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6089         emitpcode(POC_XORFW,popGet(AOP(left),offset));
6090         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6091         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
6092       }
6093       if ( AOP_TYPE(result) != AOP_ACC){
6094         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6095         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
6096       }
6097     }
6098   }
6099
6100   release :
6101     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6102   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6103   freeAsmop(result,NULL,ic,TRUE);     
6104 }
6105
6106 /*-----------------------------------------------------------------*/
6107 /* genInline - write the inline code out                           */
6108 /*-----------------------------------------------------------------*/
6109 static void genInline (iCode *ic)
6110 {
6111     char *buffer, *bp, *bp1;
6112     
6113     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6114
6115     _G.inLine += (!options.asmpeep);
6116
6117     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6118     strcpy(buffer,IC_INLINE(ic));
6119
6120     /* emit each line as a code */
6121     while (*bp) {
6122         if (*bp == '\n') {
6123             *bp++ = '\0';
6124
6125             if(*bp1)
6126               addpCode2pBlock(pb,AssembleLine(bp1));
6127             bp1 = bp;
6128         } else {
6129             if (*bp == ':') {
6130                 bp++;
6131                 *bp = '\0';
6132                 bp++;
6133                 pic14_emitcode(bp1,"");
6134                 bp1 = bp;
6135             } else
6136                 bp++;
6137         }
6138     }
6139     if ((bp1 != bp) && *bp1)
6140       addpCode2pBlock(pb,AssembleLine(bp1));
6141
6142     Safe_free(buffer);
6143
6144     _G.inLine -= (!options.asmpeep);
6145 }
6146
6147 /*-----------------------------------------------------------------*/
6148 /* genRRC - rotate right with carry                                */
6149 /*-----------------------------------------------------------------*/
6150 static void genRRC (iCode *ic)
6151 {
6152   operand *left , *result ;
6153   int size, offset = 0, same;
6154
6155   /* rotate right with carry */
6156   left = IC_LEFT(ic);
6157   result=IC_RESULT(ic);
6158   aopOp (left,ic,FALSE);
6159   aopOp (result,ic,FALSE);
6160
6161   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6162
6163   same = pic14_sameRegs(AOP(result),AOP(left));
6164
6165   size = AOP_SIZE(result);    
6166
6167   /* get the lsb and put it into the carry */
6168   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6169
6170   offset = 0 ;
6171
6172   while(size--) {
6173
6174     if(same) {
6175       emitpcode(POC_RRF, popGet(AOP(left),offset));
6176     } else {
6177       emitpcode(POC_RRFW, popGet(AOP(left),offset));
6178       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6179     }
6180
6181     offset++;
6182   }
6183
6184   freeAsmop(left,NULL,ic,TRUE);
6185   freeAsmop(result,NULL,ic,TRUE);
6186 }
6187
6188 /*-----------------------------------------------------------------*/
6189 /* genRLC - generate code for rotate left with carry               */
6190 /*-----------------------------------------------------------------*/
6191 static void genRLC (iCode *ic)
6192 {    
6193   operand *left , *result ;
6194   int size, offset = 0;
6195   int same;
6196
6197   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6198   /* rotate right with carry */
6199   left = IC_LEFT(ic);
6200   result=IC_RESULT(ic);
6201   aopOp (left,ic,FALSE);
6202   aopOp (result,ic,FALSE);
6203
6204   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6205
6206   same = pic14_sameRegs(AOP(result),AOP(left));
6207
6208   /* move it to the result */
6209   size = AOP_SIZE(result);    
6210
6211   /* get the msb and put it into the carry */
6212   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6213
6214   offset = 0 ;
6215
6216   while(size--) {
6217
6218     if(same) {
6219       emitpcode(POC_RLF, popGet(AOP(left),offset));
6220     } else {
6221       emitpcode(POC_RLFW, popGet(AOP(left),offset));
6222       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6223     }
6224
6225     offset++;
6226   }
6227
6228
6229   freeAsmop(left,NULL,ic,TRUE);
6230   freeAsmop(result,NULL,ic,TRUE);
6231 }
6232
6233 /*-----------------------------------------------------------------*/
6234 /* genGetHbit - generates code get highest order bit               */
6235 /*-----------------------------------------------------------------*/
6236 static void genGetHbit (iCode *ic)
6237 {
6238     operand *left, *result;
6239     left = IC_LEFT(ic);
6240     result=IC_RESULT(ic);
6241     aopOp (left,ic,FALSE);
6242     aopOp (result,ic,FALSE);
6243
6244     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6245     /* get the highest order byte into a */
6246     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6247     if(AOP_TYPE(result) == AOP_CRY){
6248         pic14_emitcode("rlc","a");
6249         pic14_outBitC(result);
6250     }
6251     else{
6252         pic14_emitcode("rl","a");
6253         pic14_emitcode("anl","a,#0x01");
6254         pic14_outAcc(result);
6255     }
6256
6257
6258     freeAsmop(left,NULL,ic,TRUE);
6259     freeAsmop(result,NULL,ic,TRUE);
6260 }
6261
6262 /*-----------------------------------------------------------------*/
6263 /* AccRol - rotate left accumulator by known count                 */
6264 /*-----------------------------------------------------------------*/
6265 static void AccRol (int shCount)
6266 {
6267     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6268     shCount &= 0x0007;              // shCount : 0..7
6269     switch(shCount){
6270         case 0 :
6271             break;
6272         case 1 :
6273             pic14_emitcode("rl","a");
6274             break;
6275         case 2 :
6276             pic14_emitcode("rl","a");
6277             pic14_emitcode("rl","a");
6278             break;
6279         case 3 :
6280             pic14_emitcode("swap","a");
6281             pic14_emitcode("rr","a");
6282             break;
6283         case 4 :
6284             pic14_emitcode("swap","a");
6285             break;
6286         case 5 :
6287             pic14_emitcode("swap","a");
6288             pic14_emitcode("rl","a");
6289             break;
6290         case 6 :
6291             pic14_emitcode("rr","a");
6292             pic14_emitcode("rr","a");
6293             break;
6294         case 7 :
6295             pic14_emitcode("rr","a");
6296             break;
6297     }
6298 }
6299
6300 /*-----------------------------------------------------------------*/
6301 /* AccLsh - left shift accumulator by known count                  */
6302 /*-----------------------------------------------------------------*/
6303 static void AccLsh (int shCount)
6304 {
6305     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6306     if(shCount != 0){
6307         if(shCount == 1)
6308             pic14_emitcode("add","a,acc");
6309         else 
6310             if(shCount == 2) {
6311             pic14_emitcode("add","a,acc");
6312             pic14_emitcode("add","a,acc");
6313         } else {
6314             /* rotate left accumulator */
6315             AccRol(shCount);
6316             /* and kill the lower order bits */
6317             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6318         }
6319     }
6320 }
6321
6322 /*-----------------------------------------------------------------*/
6323 /* AccRsh - right shift accumulator by known count                 */
6324 /*-----------------------------------------------------------------*/
6325 static void AccRsh (int shCount)
6326 {
6327     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6328     if(shCount != 0){
6329         if(shCount == 1){
6330             CLRC;
6331             pic14_emitcode("rrc","a");
6332         } else {
6333             /* rotate right accumulator */
6334             AccRol(8 - shCount);
6335             /* and kill the higher order bits */
6336             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6337         }
6338     }
6339 }
6340
6341 #if 0
6342 /*-----------------------------------------------------------------*/
6343 /* AccSRsh - signed right shift accumulator by known count                 */
6344 /*-----------------------------------------------------------------*/
6345 static void AccSRsh (int shCount)
6346 {
6347     symbol *tlbl ;
6348     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6349     if(shCount != 0){
6350         if(shCount == 1){
6351             pic14_emitcode("mov","c,acc.7");
6352             pic14_emitcode("rrc","a");
6353         } else if(shCount == 2){
6354             pic14_emitcode("mov","c,acc.7");
6355             pic14_emitcode("rrc","a");
6356             pic14_emitcode("mov","c,acc.7");
6357             pic14_emitcode("rrc","a");
6358         } else {
6359             tlbl = newiTempLabel(NULL);
6360             /* rotate right accumulator */
6361             AccRol(8 - shCount);
6362             /* and kill the higher order bits */
6363             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6364             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6365             pic14_emitcode("orl","a,#0x%02x",
6366                      (unsigned char)~SRMask[shCount]);
6367             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6368         }
6369     }
6370 }
6371 #endif
6372 /*-----------------------------------------------------------------*/
6373 /* shiftR1Left2Result - shift right one byte from left to result   */
6374 /*-----------------------------------------------------------------*/
6375 static void shiftR1Left2ResultSigned (operand *left, int offl,
6376                                 operand *result, int offr,
6377                                 int shCount)
6378 {
6379   int same;
6380
6381   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6382
6383   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6384
6385   switch(shCount) {
6386   case 1:
6387     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6388     if(same) 
6389       emitpcode(POC_RRF, popGet(AOP(result),offr));
6390     else {
6391       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6392       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6393     }
6394
6395     break;
6396   case 2:
6397
6398     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6399     if(same) 
6400       emitpcode(POC_RRF, popGet(AOP(result),offr));
6401     else {
6402       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6403       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6404     }
6405     emitpcode(POC_RLFW, popGet(AOP(result),offr));
6406     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6407
6408     break;
6409
6410   case 3:
6411     if(same)
6412       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6413     else {
6414       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6415       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6416     }
6417
6418     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6419     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6420     emitpcode(POC_ANDLW, popGetLit(0x1f));
6421
6422     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6423     emitpcode(POC_IORLW, popGetLit(0xe0));
6424
6425     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6426     break;
6427
6428   case 4:
6429     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6430     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6431     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6432     emitpcode(POC_IORLW,  popGetLit(0xf0));
6433     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6434     break;
6435   case 5:
6436     if(same) {
6437       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6438     } else {
6439       emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6440       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6441     }
6442     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6443     emitpcode(POC_ANDLW,  popGetLit(0x07));
6444     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6445     emitpcode(POC_IORLW,  popGetLit(0xf8));
6446     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6447     break;
6448
6449   case 6:
6450     if(same) {
6451       emitpcode(POC_MOVLW, popGetLit(0x00));
6452       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6453       emitpcode(POC_MOVLW, popGetLit(0xfe));
6454       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6455       emitpcode(POC_IORLW, popGetLit(0x01));
6456       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6457     } else {
6458       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6459       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6460       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6461       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6462       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6463     }
6464     break;
6465
6466   case 7:
6467     if(same) {
6468       emitpcode(POC_MOVLW, popGetLit(0x00));
6469       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6470       emitpcode(POC_MOVLW, popGetLit(0xff));
6471       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6472     } else {
6473       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6474       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6475       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6476     }
6477
6478   default:
6479     break;
6480   }
6481 }
6482
6483 /*-----------------------------------------------------------------*/
6484 /* shiftR1Left2Result - shift right one byte from left to result   */
6485 /*-----------------------------------------------------------------*/
6486 static void shiftR1Left2Result (operand *left, int offl,
6487                                 operand *result, int offr,
6488                                 int shCount, int sign)
6489 {
6490   int same;
6491
6492   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6493
6494   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6495
6496   /* Copy the msb into the carry if signed. */
6497   if(sign) {
6498     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6499     return;
6500   }
6501
6502
6503
6504   switch(shCount) {
6505   case 1:
6506     emitCLRC;
6507     if(same) 
6508       emitpcode(POC_RRF, popGet(AOP(result),offr));
6509     else {
6510       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6511       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6512     }
6513     break;
6514   case 2:
6515     emitCLRC;
6516     if(same) {
6517       emitpcode(POC_RRF, popGet(AOP(result),offr));
6518     } else {
6519       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6520       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6521     }
6522     emitCLRC;
6523     emitpcode(POC_RRF, popGet(AOP(result),offr));
6524
6525     break;
6526   case 3:
6527     if(same)
6528       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6529     else {
6530       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6531       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6532     }
6533
6534     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6535     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6536     emitpcode(POC_ANDLW, popGetLit(0x1f));
6537     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6538     break;
6539       
6540   case 4:
6541     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6542     emitpcode(POC_ANDLW, popGetLit(0x0f));
6543     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6544     break;
6545
6546   case 5:
6547     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6548     emitpcode(POC_ANDLW, popGetLit(0x0f));
6549     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6550     emitCLRC;
6551     emitpcode(POC_RRF, popGet(AOP(result),offr));
6552
6553     break;
6554   case 6:
6555
6556     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6557     emitpcode(POC_ANDLW, popGetLit(0x80));
6558     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6559     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6560     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6561     break;
6562
6563   case 7:
6564
6565     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6566     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6567     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6568
6569     break;
6570
6571   default:
6572     break;
6573   }
6574 }
6575
6576 /*-----------------------------------------------------------------*/
6577 /* shiftL1Left2Result - shift left one byte from left to result    */
6578 /*-----------------------------------------------------------------*/
6579 static void shiftL1Left2Result (operand *left, int offl,
6580                                 operand *result, int offr, int shCount)
6581 {
6582   int same;
6583
6584   //    char *l;
6585   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6586
6587   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6588   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6589     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6590     //    MOVA(l);
6591     /* shift left accumulator */
6592     //AccLsh(shCount); // don't comment out just yet...
6593   //    aopPut(AOP(result),"a",offr);
6594
6595   switch(shCount) {
6596   case 1:
6597     /* Shift left 1 bit position */
6598     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6599     if(same) {
6600       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6601     } else {
6602       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6603       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6604     }
6605     break;
6606   case 2:
6607     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6608     emitpcode(POC_ANDLW,popGetLit(0x7e));
6609     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6610     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6611     break;
6612   case 3:
6613     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6614     emitpcode(POC_ANDLW,popGetLit(0x3e));
6615     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6616     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6617     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6618     break;
6619   case 4:
6620     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6621     emitpcode(POC_ANDLW, popGetLit(0xf0));
6622     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6623     break;
6624   case 5:
6625     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6626     emitpcode(POC_ANDLW, popGetLit(0xf0));
6627     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6628     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6629     break;
6630   case 6:
6631     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6632     emitpcode(POC_ANDLW, popGetLit(0x30));
6633     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6634     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6635     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6636     break;
6637   case 7:
6638     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6639     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6640     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6641     break;
6642
6643   default:
6644     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6645   }
6646
6647 }
6648
6649 /*-----------------------------------------------------------------*/
6650 /* movLeft2Result - move byte from left to result                  */
6651 /*-----------------------------------------------------------------*/
6652 static void movLeft2Result (operand *left, int offl,
6653                             operand *result, int offr)
6654 {
6655   char *l;
6656   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6657   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6658     l = aopGet(AOP(left),offl,FALSE,FALSE);
6659
6660     if (*l == '@' && (IS_AOP_PREG(result))) {
6661       pic14_emitcode("mov","a,%s",l);
6662       aopPut(AOP(result),"a",offr);
6663     } else {
6664       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6665       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6666     }
6667   }
6668 }
6669
6670 /*-----------------------------------------------------------------*/
6671 /* shiftL2Left2Result - shift left two bytes from left to result   */
6672 /*-----------------------------------------------------------------*/
6673 static void shiftL2Left2Result (operand *left, int offl,
6674                                 operand *result, int offr, int shCount)
6675 {
6676
6677
6678   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6679
6680   if(pic14_sameRegs(AOP(result), AOP(left))) {
6681     switch(shCount) {
6682     case 0:
6683       break;
6684     case 1:
6685     case 2:
6686     case 3:
6687
6688       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6689       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6690       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6691
6692       while(--shCount) {
6693         emitCLRC;
6694         emitpcode(POC_RLF, popGet(AOP(result),offr));
6695         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6696       }
6697
6698       break;
6699     case 4:
6700     case 5:
6701       emitpcode(POC_MOVLW, popGetLit(0x0f));
6702       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6703       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6704       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6705       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6706       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6707       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6708       if(shCount >=5) {
6709         emitpcode(POC_RLF, popGet(AOP(result),offr));
6710         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6711       }
6712       break;
6713     case 6:
6714       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6715       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6716       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6717       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6718       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6719       emitpcode(POC_ANDLW,popGetLit(0xc0));
6720       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6721       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6722       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6723       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6724       break;
6725     case 7:
6726       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6727       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6728       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6729       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6730       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6731     }
6732
6733   } else {
6734     switch(shCount) {
6735     case 0:
6736       break;
6737     case 1:
6738     case 2:
6739     case 3:
6740       /* note, use a mov/add for the shift since the mov has a
6741          chance of getting optimized out */
6742       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6743       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6744       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6745       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6746       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6747
6748       while(--shCount) {
6749         emitCLRC;
6750         emitpcode(POC_RLF, popGet(AOP(result),offr));
6751         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6752       }
6753       break;
6754
6755     case 4:
6756     case 5:
6757       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6758       emitpcode(POC_ANDLW, popGetLit(0xF0));
6759       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6760       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6761       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6762       emitpcode(POC_ANDLW, popGetLit(0xF0));
6763       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6764       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6765
6766
6767       if(shCount == 5) {
6768         emitpcode(POC_RLF, popGet(AOP(result),offr));
6769         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6770       }
6771       break;
6772     case 6:
6773       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6774       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6775       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6776       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6777
6778       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6779       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6780       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6781       emitpcode(POC_ANDLW,popGetLit(0xc0));
6782       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6783       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6784       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6785       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6786       break;
6787     case 7:
6788       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6789       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6790       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6791       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6792       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6793     }
6794   }
6795
6796 }
6797 /*-----------------------------------------------------------------*/
6798 /* shiftR2Left2Result - shift right two bytes from left to result  */
6799 /*-----------------------------------------------------------------*/
6800 static void shiftR2Left2Result (operand *left, int offl,
6801                                 operand *result, int offr,
6802                                 int shCount, int sign)
6803 {
6804   int same=0;
6805
6806   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6807   same = pic14_sameRegs(AOP(result), AOP(left));
6808
6809   if(same && ((offl + MSB16) == offr)){
6810     same=1;
6811     /* don't crash result[offr] */
6812     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6813     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6814   }
6815 /* else {
6816     movLeft2Result(left,offl, result, offr);
6817     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6818   }
6819 */
6820   /* a:x >> shCount (x = lsb(result))*/
6821 /*
6822   if(sign)
6823     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6824   else {
6825     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6826 */
6827   switch(shCount) {
6828   case 0:
6829     break;
6830   case 1:
6831   case 2:
6832   case 3:
6833     if(sign)
6834       emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6835     else
6836       emitCLRC;
6837
6838     if(same) {
6839       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6840       emitpcode(POC_RRF,popGet(AOP(result),offr));
6841     } else {
6842       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6843       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6844       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6845       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6846     }
6847
6848     while(--shCount) {
6849       if(sign)
6850         emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6851       else
6852         emitCLRC;
6853       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6854       emitpcode(POC_RRF,popGet(AOP(result),offr));
6855     }
6856     break;
6857   case 4:
6858   case 5:
6859     if(same) {
6860
6861       emitpcode(POC_MOVLW, popGetLit(0xf0));
6862       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6863       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6864
6865       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6866       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6867       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6868       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6869     } else {
6870       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6871       emitpcode(POC_ANDLW, popGetLit(0x0f));
6872       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6873
6874       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6875       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6876       emitpcode(POC_ANDLW, popGetLit(0xf0));
6877       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6878       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6879     }
6880
6881     if(shCount >=5) {
6882       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6883       emitpcode(POC_RRF, popGet(AOP(result),offr));
6884     }
6885
6886     if(sign) {
6887       emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6888       emitpcode(POC_BTFSC, 
6889                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6890       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6891     }
6892
6893     break;
6894
6895   case 6:
6896     if(same) {
6897
6898       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6899       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6900
6901       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6902       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6903       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6904       emitpcode(POC_ANDLW,popGetLit(0x03));
6905       if(sign) {
6906         emitpcode(POC_BTFSC, 
6907                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6908         emitpcode(POC_IORLW,popGetLit(0xfc));
6909       }
6910       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6911       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6912       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6913       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6914     } else {
6915       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6916       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6917       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6918       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6919       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6920       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6921       emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6922       emitpcode(POC_ANDLW,popGetLit(0x03));
6923       if(sign) {
6924         emitpcode(POC_BTFSC, 
6925                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6926         emitpcode(POC_IORLW,popGetLit(0xfc));
6927       }
6928       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6929       //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6930
6931         
6932     }
6933
6934     break;
6935   case 7:
6936     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6937     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6938     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6939     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6940     if(sign) {
6941       emitSKPNC;
6942       emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6943     } else 
6944       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6945   }
6946 }
6947
6948
6949 /*-----------------------------------------------------------------*/
6950 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6951 /*-----------------------------------------------------------------*/
6952 static void shiftLLeftOrResult (operand *left, int offl,
6953                                 operand *result, int offr, int shCount)
6954 {
6955     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6956     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6957     /* shift left accumulator */
6958     AccLsh(shCount);
6959     /* or with result */
6960     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6961     /* back to result */
6962     aopPut(AOP(result),"a",offr);
6963 }
6964
6965 /*-----------------------------------------------------------------*/
6966 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6967 /*-----------------------------------------------------------------*/
6968 static void shiftRLeftOrResult (operand *left, int offl,
6969                                 operand *result, int offr, int shCount)
6970 {
6971     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6972     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6973     /* shift right accumulator */
6974     AccRsh(shCount);
6975     /* or with result */
6976     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6977     /* back to result */
6978     aopPut(AOP(result),"a",offr);
6979 }
6980
6981 /*-----------------------------------------------------------------*/
6982 /* genlshOne - left shift a one byte quantity by known count       */
6983 /*-----------------------------------------------------------------*/
6984 static void genlshOne (operand *result, operand *left, int shCount)
6985 {       
6986     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6987     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6988 }
6989
6990 /*-----------------------------------------------------------------*/
6991 /* genlshTwo - left shift two bytes by known amount != 0           */
6992 /*-----------------------------------------------------------------*/
6993 static void genlshTwo (operand *result,operand *left, int shCount)
6994 {
6995     int size;
6996     
6997     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6998     size = pic14_getDataSize(result);
6999
7000     /* if shCount >= 8 */
7001     if (shCount >= 8) {
7002         shCount -= 8 ;
7003
7004         if (size > 1){
7005             if (shCount)
7006                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7007             else 
7008                 movLeft2Result(left, LSB, result, MSB16);
7009         }
7010         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7011     }
7012
7013     /*  1 <= shCount <= 7 */
7014     else {  
7015         if(size == 1)
7016             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7017         else 
7018             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7019     }
7020 }
7021
7022 /*-----------------------------------------------------------------*/
7023 /* shiftLLong - shift left one long from left to result            */
7024 /* offl = LSB or MSB16                                             */
7025 /*-----------------------------------------------------------------*/
7026 static void shiftLLong (operand *left, operand *result, int offr )
7027 {
7028     char *l;
7029     int size = AOP_SIZE(result);
7030
7031     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7032     if(size >= LSB+offr){
7033         l = aopGet(AOP(left),LSB,FALSE,FALSE);
7034         MOVA(l);
7035         pic14_emitcode("add","a,acc");
7036         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7037             size >= MSB16+offr && offr != LSB )
7038             pic14_emitcode("xch","a,%s",
7039                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7040         else        
7041             aopPut(AOP(result),"a",LSB+offr);
7042     }
7043
7044     if(size >= MSB16+offr){
7045         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7046             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7047             MOVA(l);
7048         }
7049         pic14_emitcode("rlc","a");
7050         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7051             size >= MSB24+offr && offr != LSB)
7052             pic14_emitcode("xch","a,%s",
7053                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7054         else        
7055             aopPut(AOP(result),"a",MSB16+offr);
7056     }
7057
7058     if(size >= MSB24+offr){
7059         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7060             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7061             MOVA(l);
7062         }
7063         pic14_emitcode("rlc","a");
7064         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7065             size >= MSB32+offr && offr != LSB )
7066             pic14_emitcode("xch","a,%s",
7067                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7068         else        
7069             aopPut(AOP(result),"a",MSB24+offr);
7070     }
7071
7072     if(size > MSB32+offr){
7073         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7074             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7075             MOVA(l);    
7076         }
7077         pic14_emitcode("rlc","a");
7078         aopPut(AOP(result),"a",MSB32+offr);
7079     }
7080     if(offr != LSB)
7081         aopPut(AOP(result),zero,LSB);       
7082 }
7083
7084 /*-----------------------------------------------------------------*/
7085 /* genlshFour - shift four byte by a known amount != 0             */
7086 /*-----------------------------------------------------------------*/
7087 static void genlshFour (operand *result, operand *left, int shCount)
7088 {
7089     int size;
7090
7091     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7092     size = AOP_SIZE(result);
7093
7094     /* if shifting more that 3 bytes */
7095     if (shCount >= 24 ) {
7096         shCount -= 24;
7097         if (shCount)
7098             /* lowest order of left goes to the highest
7099             order of the destination */
7100             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7101         else
7102             movLeft2Result(left, LSB, result, MSB32);
7103         aopPut(AOP(result),zero,LSB);
7104         aopPut(AOP(result),zero,MSB16);
7105         aopPut(AOP(result),zero,MSB32);
7106         return;
7107     }
7108
7109     /* more than two bytes */
7110     else if ( shCount >= 16 ) {
7111         /* lower order two bytes goes to higher order two bytes */
7112         shCount -= 16;
7113         /* if some more remaining */
7114         if (shCount)
7115             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7116         else {
7117             movLeft2Result(left, MSB16, result, MSB32);
7118             movLeft2Result(left, LSB, result, MSB24);
7119         }
7120         aopPut(AOP(result),zero,MSB16);
7121         aopPut(AOP(result),zero,LSB);
7122         return;
7123     }    
7124
7125     /* if more than 1 byte */
7126     else if ( shCount >= 8 ) {
7127         /* lower order three bytes goes to higher order  three bytes */
7128         shCount -= 8;
7129         if(size == 2){
7130             if(shCount)
7131                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7132             else
7133                 movLeft2Result(left, LSB, result, MSB16);
7134         }
7135         else{   /* size = 4 */
7136             if(shCount == 0){
7137                 movLeft2Result(left, MSB24, result, MSB32);
7138                 movLeft2Result(left, MSB16, result, MSB24);
7139                 movLeft2Result(left, LSB, result, MSB16);
7140                 aopPut(AOP(result),zero,LSB);
7141             }
7142             else if(shCount == 1)
7143                 shiftLLong(left, result, MSB16);
7144             else{
7145                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7146                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7147                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7148                 aopPut(AOP(result),zero,LSB);
7149             }
7150         }
7151     }
7152
7153     /* 1 <= shCount <= 7 */
7154     else if(shCount <= 2){
7155         shiftLLong(left, result, LSB);
7156         if(shCount == 2)
7157             shiftLLong(result, result, LSB);
7158     }
7159     /* 3 <= shCount <= 7, optimize */
7160     else{
7161         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7162         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7163         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7164     }
7165 }
7166
7167 /*-----------------------------------------------------------------*/
7168 /* genLeftShiftLiteral - left shifting by known count              */
7169 /*-----------------------------------------------------------------*/
7170 static void genLeftShiftLiteral (operand *left,
7171                                  operand *right,
7172                                  operand *result,
7173                                  iCode *ic)
7174 {    
7175     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7176     int size;
7177
7178     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7179     freeAsmop(right,NULL,ic,TRUE);
7180
7181     aopOp(left,ic,FALSE);
7182     aopOp(result,ic,FALSE);
7183
7184     size = getSize(operandType(result));
7185
7186 #if VIEW_SIZE
7187     pic14_emitcode("; shift left ","result %d, left %d",size,
7188              AOP_SIZE(left));
7189 #endif
7190
7191     /* I suppose that the left size >= result size */
7192     if(shCount == 0){
7193         while(size--){
7194             movLeft2Result(left, size, result, size);
7195         }
7196     }
7197
7198     else if(shCount >= (size * 8))
7199         while(size--)
7200             aopPut(AOP(result),zero,size);
7201     else{
7202         switch (size) {
7203             case 1:
7204                 genlshOne (result,left,shCount);
7205                 break;
7206
7207             case 2:
7208             case 3:
7209                 genlshTwo (result,left,shCount);
7210                 break;
7211
7212             case 4:
7213                 genlshFour (result,left,shCount);
7214                 break;
7215         }
7216     }
7217     freeAsmop(left,NULL,ic,TRUE);
7218     freeAsmop(result,NULL,ic,TRUE);
7219 }
7220
7221 /*-----------------------------------------------------------------*
7222  * genMultiAsm - repeat assembly instruction for size of register.
7223  * if endian == 1, then the high byte (i.e base address + size of 
7224  * register) is used first else the low byte is used first;
7225  *-----------------------------------------------------------------*/
7226 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7227 {
7228
7229   int offset = 0;
7230
7231   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7232
7233   if(!reg)
7234     return;
7235
7236   if(!endian) {
7237     endian = 1;
7238   } else {
7239     endian = -1;
7240     offset = size-1;
7241   }
7242
7243   while(size--) {
7244     emitpcode(poc,    popGet(AOP(reg),offset));
7245     offset += endian;
7246   }
7247
7248 }
7249 /*-----------------------------------------------------------------*/
7250 /* genLeftShift - generates code for left shifting                 */
7251 /*-----------------------------------------------------------------*/
7252 static void genLeftShift (iCode *ic)
7253 {
7254   operand *left,*right, *result;
7255   int size, offset;
7256   char *l;
7257   symbol *tlbl , *tlbl1;
7258   pCodeOp *pctemp;
7259
7260   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7261
7262   right = IC_RIGHT(ic);
7263   left  = IC_LEFT(ic);
7264   result = IC_RESULT(ic);
7265
7266   aopOp(right,ic,FALSE);
7267
7268   /* if the shift count is known then do it 
7269      as efficiently as possible */
7270   if (AOP_TYPE(right) == AOP_LIT) {
7271     genLeftShiftLiteral (left,right,result,ic);
7272     return ;
7273   }
7274
7275   /* shift count is unknown then we have to form 
7276      a loop get the loop count in B : Note: we take
7277      only the lower order byte since shifting
7278      more that 32 bits make no sense anyway, ( the
7279      largest size of an object can be only 32 bits ) */  
7280
7281     
7282   aopOp(left,ic,FALSE);
7283   aopOp(result,ic,FALSE);
7284
7285   /* now move the left to the result if they are not the
7286      same */
7287   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7288       AOP_SIZE(result) > 1) {
7289
7290     size = AOP_SIZE(result);
7291     offset=0;
7292     while (size--) {
7293       l = aopGet(AOP(left),offset,FALSE,TRUE);
7294       if (*l == '@' && (IS_AOP_PREG(result))) {
7295
7296         pic14_emitcode("mov","a,%s",l);
7297         aopPut(AOP(result),"a",offset);
7298       } else {
7299         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7300         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7301         //aopPut(AOP(result),l,offset);
7302       }
7303       offset++;
7304     }
7305   }
7306
7307   size = AOP_SIZE(result);
7308
7309   /* if it is only one byte then */
7310   if (size == 1) {
7311     if(optimized_for_speed) {
7312       emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7313       emitpcode(POC_ANDLW,  popGetLit(0xf0));
7314       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7315       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7316       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7317       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7318       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7319       emitpcode(POC_RLFW,   popGet(AOP(result),0));
7320       emitpcode(POC_ANDLW,  popGetLit(0xfe));
7321       emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7322       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7323       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7324     } else {
7325
7326       tlbl = newiTempLabel(NULL);
7327       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7328         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7329         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7330       }
7331
7332       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7333       emitpcode(POC_RRF,    popGet(AOP(result),0));
7334       emitpLabel(tlbl->key);
7335       emitpcode(POC_RLF,    popGet(AOP(result),0));
7336       emitpcode(POC_ADDLW,  popGetLit(1));
7337       emitSKPC;
7338       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7339     }
7340     goto release ;
7341   }
7342     
7343   if (pic14_sameRegs(AOP(left),AOP(result))) {
7344
7345     tlbl = newiTempLabel(NULL);
7346     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7347     genMultiAsm(POC_RRF, result, size,1);
7348     emitpLabel(tlbl->key);
7349     genMultiAsm(POC_RLF, result, size,0);
7350     emitpcode(POC_ADDLW,  popGetLit(1));
7351     emitSKPC;
7352     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7353     goto release;
7354   }
7355
7356   //tlbl = newiTempLabel(NULL);
7357   //offset = 0 ;   
7358   //tlbl1 = newiTempLabel(NULL);
7359
7360   //reAdjustPreg(AOP(result));    
7361     
7362   //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7363   //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7364   //l = aopGet(AOP(result),offset,FALSE,FALSE);
7365   //MOVA(l);
7366   //pic14_emitcode("add","a,acc");         
7367   //aopPut(AOP(result),"a",offset++);
7368   //while (--size) {
7369   //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7370   //  MOVA(l);
7371   //  pic14_emitcode("rlc","a");         
7372   //  aopPut(AOP(result),"a",offset++);
7373   //}
7374   //reAdjustPreg(AOP(result));
7375
7376   //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7377   //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7378
7379
7380   tlbl = newiTempLabel(NULL);
7381   tlbl1= newiTempLabel(NULL);
7382
7383   size = AOP_SIZE(result);
7384   offset = 1;
7385
7386   pctemp = popGetTempReg();  /* grab a temporary working register. */
7387
7388   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7389
7390   /* offset should be 0, 1 or 3 */
7391   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7392   emitSKPNZ;
7393   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7394
7395   emitpcode(POC_MOVWF, pctemp);
7396
7397
7398   emitpLabel(tlbl->key);
7399
7400   emitCLRC;
7401   emitpcode(POC_RLF,  popGet(AOP(result),0));
7402   while(--size)
7403     emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7404
7405   emitpcode(POC_DECFSZ,  pctemp);
7406   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7407   emitpLabel(tlbl1->key);
7408
7409   popReleaseTempReg(pctemp);
7410
7411
7412  release:
7413   freeAsmop (right,NULL,ic,TRUE);
7414   freeAsmop(left,NULL,ic,TRUE);
7415   freeAsmop(result,NULL,ic,TRUE);
7416 }
7417
7418 /*-----------------------------------------------------------------*/
7419 /* genrshOne - right shift a one byte quantity by known count      */
7420 /*-----------------------------------------------------------------*/
7421 static void genrshOne (operand *result, operand *left,
7422                        int shCount, int sign)
7423 {
7424     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7425     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7426 }
7427
7428 /*-----------------------------------------------------------------*/
7429 /* genrshTwo - right shift two bytes by known amount != 0          */
7430 /*-----------------------------------------------------------------*/
7431 static void genrshTwo (operand *result,operand *left,
7432                        int shCount, int sign)
7433 {
7434   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7435   /* if shCount >= 8 */
7436   if (shCount >= 8) {
7437     shCount -= 8 ;
7438     if (shCount)
7439       shiftR1Left2Result(left, MSB16, result, LSB,
7440                          shCount, sign);
7441     else
7442       movLeft2Result(left, MSB16, result, LSB);
7443
7444     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7445
7446     if(sign) {
7447       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7448       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7449     }
7450   }
7451
7452   /*  1 <= shCount <= 7 */
7453   else
7454     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7455 }
7456
7457 /*-----------------------------------------------------------------*/
7458 /* shiftRLong - shift right one long from left to result           */
7459 /* offl = LSB or MSB16                                             */
7460 /*-----------------------------------------------------------------*/
7461 static void shiftRLong (operand *left, int offl,
7462                         operand *result, int sign)
7463 {
7464     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7465     if(!sign)
7466         pic14_emitcode("clr","c");
7467     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7468     if(sign)
7469         pic14_emitcode("mov","c,acc.7");
7470     pic14_emitcode("rrc","a");
7471     aopPut(AOP(result),"a",MSB32-offl);
7472     if(offl == MSB16)
7473         /* add sign of "a" */
7474         addSign(result, MSB32, sign);
7475
7476     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7477     pic14_emitcode("rrc","a");
7478     aopPut(AOP(result),"a",MSB24-offl);
7479
7480     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7481     pic14_emitcode("rrc","a");
7482     aopPut(AOP(result),"a",MSB16-offl);
7483
7484     if(offl == LSB){
7485         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7486         pic14_emitcode("rrc","a");
7487         aopPut(AOP(result),"a",LSB);
7488     }
7489 }
7490
7491 /*-----------------------------------------------------------------*/
7492 /* genrshFour - shift four byte by a known amount != 0             */
7493 /*-----------------------------------------------------------------*/
7494 static void genrshFour (operand *result, operand *left,
7495                         int shCount, int sign)
7496 {
7497   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7498   /* if shifting more that 3 bytes */
7499   if(shCount >= 24 ) {
7500     shCount -= 24;
7501     if(shCount)
7502       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7503     else
7504       movLeft2Result(left, MSB32, result, LSB);
7505
7506     addSign(result, MSB16, sign);
7507   }
7508   else if(shCount >= 16){
7509     shCount -= 16;
7510     if(shCount)
7511       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7512     else{
7513       movLeft2Result(left, MSB24, result, LSB);
7514       movLeft2Result(left, MSB32, result, MSB16);
7515     }
7516     addSign(result, MSB24, sign);
7517   }
7518   else if(shCount >= 8){
7519     shCount -= 8;
7520     if(shCount == 1)
7521       shiftRLong(left, MSB16, result, sign);
7522     else if(shCount == 0){
7523       movLeft2Result(left, MSB16, result, LSB);
7524       movLeft2Result(left, MSB24, result, MSB16);
7525       movLeft2Result(left, MSB32, result, MSB24);
7526       addSign(result, MSB32, sign);
7527     }
7528     else{
7529       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7530       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7531       /* the last shift is signed */
7532       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7533       addSign(result, MSB32, sign);
7534     }
7535   }
7536   else{   /* 1 <= shCount <= 7 */
7537     if(shCount <= 2){
7538       shiftRLong(left, LSB, result, sign);
7539       if(shCount == 2)
7540         shiftRLong(result, LSB, result, sign);
7541     }
7542     else{
7543       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7544       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7545       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7546     }
7547   }
7548 }
7549
7550 /*-----------------------------------------------------------------*/
7551 /* genRightShiftLiteral - right shifting by known count            */
7552 /*-----------------------------------------------------------------*/
7553 static void genRightShiftLiteral (operand *left,
7554                                   operand *right,
7555                                   operand *result,
7556                                   iCode *ic,
7557                                   int sign)
7558 {    
7559   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7560   int lsize,res_size;
7561
7562   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7563   freeAsmop(right,NULL,ic,TRUE);
7564
7565   aopOp(left,ic,FALSE);
7566   aopOp(result,ic,FALSE);
7567
7568 #if VIEW_SIZE
7569   pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7570                  AOP_SIZE(left));
7571 #endif
7572
7573   lsize = pic14_getDataSize(left);
7574   res_size = pic14_getDataSize(result);
7575   /* test the LEFT size !!! */
7576
7577   /* I suppose that the left size >= result size */
7578   if(shCount == 0){
7579     while(res_size--)
7580       movLeft2Result(left, lsize, result, res_size);
7581   }
7582
7583   else if(shCount >= (lsize * 8)){
7584
7585     if(res_size == 1) {
7586       emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7587       if(sign) {
7588         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7589         emitpcode(POC_DECF, popGet(AOP(result),LSB));
7590       }
7591     } else {
7592
7593       if(sign) {
7594         emitpcode(POC_MOVLW, popGetLit(0));
7595         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7596         emitpcode(POC_MOVLW, popGetLit(0xff));
7597         while(res_size--)
7598           emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7599
7600       } else {
7601
7602         while(res_size--)
7603           emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7604       }
7605     }
7606   } else {
7607
7608     switch (res_size) {
7609     case 1:
7610       genrshOne (result,left,shCount,sign);
7611       break;
7612
7613     case 2:
7614       genrshTwo (result,left,shCount,sign);
7615       break;
7616
7617     case 4:
7618       genrshFour (result,left,shCount,sign);
7619       break;
7620     default :
7621       break;
7622     }
7623
7624   }
7625
7626   freeAsmop(left,NULL,ic,TRUE);
7627   freeAsmop(result,NULL,ic,TRUE);
7628 }
7629
7630 /*-----------------------------------------------------------------*/
7631 /* genSignedRightShift - right shift of signed number              */
7632 /*-----------------------------------------------------------------*/
7633 static void genSignedRightShift (iCode *ic)
7634 {
7635   operand *right, *left, *result;
7636   int size, offset;
7637   //  char *l;
7638   symbol *tlbl, *tlbl1 ;
7639   pCodeOp *pctemp;
7640
7641   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7642
7643   /* we do it the hard way put the shift count in b
7644      and loop thru preserving the sign */
7645   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7646
7647   right = IC_RIGHT(ic);
7648   left  = IC_LEFT(ic);
7649   result = IC_RESULT(ic);
7650
7651   aopOp(right,ic,FALSE);  
7652   aopOp(left,ic,FALSE);
7653   aopOp(result,ic,FALSE);
7654
7655
7656   if ( AOP_TYPE(right) == AOP_LIT) {
7657     genRightShiftLiteral (left,right,result,ic,1);
7658     return ;
7659   }
7660   /* shift count is unknown then we have to form 
7661      a loop get the loop count in B : Note: we take
7662      only the lower order byte since shifting
7663      more that 32 bits make no sense anyway, ( the
7664      largest size of an object can be only 32 bits ) */  
7665
7666   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7667   //pic14_emitcode("inc","b");
7668   //freeAsmop (right,NULL,ic,TRUE);
7669   //aopOp(left,ic,FALSE);
7670   //aopOp(result,ic,FALSE);
7671
7672   /* now move the left to the result if they are not the
7673      same */
7674   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7675       AOP_SIZE(result) > 1) {
7676
7677     size = AOP_SIZE(result);
7678     offset=0;
7679     while (size--) { 
7680       /*
7681         l = aopGet(AOP(left),offset,FALSE,TRUE);
7682         if (*l == '@' && IS_AOP_PREG(result)) {
7683
7684         pic14_emitcode("mov","a,%s",l);
7685         aopPut(AOP(result),"a",offset);
7686         } else
7687         aopPut(AOP(result),l,offset);
7688       */
7689       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7690       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7691
7692       offset++;
7693     }
7694   }
7695
7696   /* mov the highest order bit to OVR */    
7697   tlbl = newiTempLabel(NULL);
7698   tlbl1= newiTempLabel(NULL);
7699
7700   size = AOP_SIZE(result);
7701   offset = size - 1;
7702
7703   pctemp = popGetTempReg();  /* grab a temporary working register. */
7704
7705   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7706
7707   /* offset should be 0, 1 or 3 */
7708   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7709   emitSKPNZ;
7710   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7711
7712   emitpcode(POC_MOVWF, pctemp);
7713
7714
7715   emitpLabel(tlbl->key);
7716
7717   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7718   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7719
7720   while(--size) {
7721     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7722   }
7723
7724   emitpcode(POC_DECFSZ,  pctemp);
7725   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7726   emitpLabel(tlbl1->key);
7727
7728   popReleaseTempReg(pctemp);
7729 #if 0
7730   size = AOP_SIZE(result);
7731   offset = size - 1;
7732   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7733   pic14_emitcode("rlc","a");
7734   pic14_emitcode("mov","ov,c");
7735   /* if it is only one byte then */
7736   if (size == 1) {
7737     l = aopGet(AOP(left),0,FALSE,FALSE);
7738     MOVA(l);
7739     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7740     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7741     pic14_emitcode("mov","c,ov");
7742     pic14_emitcode("rrc","a");
7743     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7744     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7745     aopPut(AOP(result),"a",0);
7746     goto release ;
7747   }
7748
7749   reAdjustPreg(AOP(result));
7750   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7751   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7752   pic14_emitcode("mov","c,ov");
7753   while (size--) {
7754     l = aopGet(AOP(result),offset,FALSE,FALSE);
7755     MOVA(l);
7756     pic14_emitcode("rrc","a");         
7757     aopPut(AOP(result),"a",offset--);
7758   }
7759   reAdjustPreg(AOP(result));
7760   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7761   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7762
7763  release:
7764 #endif
7765
7766   freeAsmop(left,NULL,ic,TRUE);
7767   freeAsmop(result,NULL,ic,TRUE);
7768   freeAsmop(right,NULL,ic,TRUE);
7769 }
7770
7771 /*-----------------------------------------------------------------*/
7772 /* genRightShift - generate code for right shifting                */
7773 /*-----------------------------------------------------------------*/
7774 static void genRightShift (iCode *ic)
7775 {
7776     operand *right, *left, *result;
7777     sym_link *retype ;
7778     int size, offset;
7779     char *l;
7780     symbol *tlbl, *tlbl1 ;
7781
7782     /* if signed then we do it the hard way preserve the
7783     sign bit moving it inwards */
7784     retype = getSpec(operandType(IC_RESULT(ic)));
7785     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7786
7787     if (!SPEC_USIGN(retype)) {
7788         genSignedRightShift (ic);
7789         return ;
7790     }
7791
7792     /* signed & unsigned types are treated the same : i.e. the
7793     signed is NOT propagated inwards : quoting from the
7794     ANSI - standard : "for E1 >> E2, is equivalent to division
7795     by 2**E2 if unsigned or if it has a non-negative value,
7796     otherwise the result is implementation defined ", MY definition
7797     is that the sign does not get propagated */
7798
7799     right = IC_RIGHT(ic);
7800     left  = IC_LEFT(ic);
7801     result = IC_RESULT(ic);
7802
7803     aopOp(right,ic,FALSE);
7804
7805     /* if the shift count is known then do it 
7806     as efficiently as possible */
7807     if (AOP_TYPE(right) == AOP_LIT) {
7808         genRightShiftLiteral (left,right,result,ic, 0);
7809         return ;
7810     }
7811
7812     /* shift count is unknown then we have to form 
7813     a loop get the loop count in B : Note: we take
7814     only the lower order byte since shifting
7815     more that 32 bits make no sense anyway, ( the
7816     largest size of an object can be only 32 bits ) */  
7817
7818     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7819     pic14_emitcode("inc","b");
7820     aopOp(left,ic,FALSE);
7821     aopOp(result,ic,FALSE);
7822
7823     /* now move the left to the result if they are not the
7824     same */
7825     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7826         AOP_SIZE(result) > 1) {
7827
7828         size = AOP_SIZE(result);
7829         offset=0;
7830         while (size--) {
7831             l = aopGet(AOP(left),offset,FALSE,TRUE);
7832             if (*l == '@' && IS_AOP_PREG(result)) {
7833
7834                 pic14_emitcode("mov","a,%s",l);
7835                 aopPut(AOP(result),"a",offset);
7836             } else
7837                 aopPut(AOP(result),l,offset);
7838             offset++;
7839         }
7840     }
7841
7842     tlbl = newiTempLabel(NULL);
7843     tlbl1= newiTempLabel(NULL);
7844     size = AOP_SIZE(result);
7845     offset = size - 1;
7846
7847     /* if it is only one byte then */
7848     if (size == 1) {
7849
7850       tlbl = newiTempLabel(NULL);
7851       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7852         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7853         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7854       }
7855
7856       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7857       emitpcode(POC_RLF,    popGet(AOP(result),0));
7858       emitpLabel(tlbl->key);
7859       emitpcode(POC_RRF,    popGet(AOP(result),0));
7860       emitpcode(POC_ADDLW,  popGetLit(1));
7861       emitSKPC;
7862       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7863
7864       goto release ;
7865     }
7866
7867     reAdjustPreg(AOP(result));
7868     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7869     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7870     CLRC;
7871     while (size--) {
7872         l = aopGet(AOP(result),offset,FALSE,FALSE);
7873         MOVA(l);
7874         pic14_emitcode("rrc","a");         
7875         aopPut(AOP(result),"a",offset--);
7876     }
7877     reAdjustPreg(AOP(result));
7878
7879     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7880     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7881
7882 release:
7883     freeAsmop(left,NULL,ic,TRUE);
7884     freeAsmop (right,NULL,ic,TRUE);
7885     freeAsmop(result,NULL,ic,TRUE);
7886 }
7887
7888 /*-----------------------------------------------------------------*/
7889 /* genUnpackBits - generates code for unpacking bits               */
7890 /*-----------------------------------------------------------------*/
7891 static void genUnpackBits (operand *result, char *rname, int ptype)
7892 {    
7893     int shCnt ;
7894     int rlen = 0 ;
7895     sym_link *etype;
7896     int offset = 0 ;
7897
7898     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7899     etype = getSpec(operandType(result));
7900
7901     /* read the first byte  */
7902     switch (ptype) {
7903
7904     case POINTER:
7905     case IPOINTER:
7906         pic14_emitcode("mov","a,@%s",rname);
7907         break;
7908         
7909     case PPOINTER:
7910         pic14_emitcode("movx","a,@%s",rname);
7911         break;
7912         
7913     case FPOINTER:
7914         pic14_emitcode("movx","a,@dptr");
7915         break;
7916
7917     case CPOINTER:
7918         pic14_emitcode("clr","a");
7919         pic14_emitcode("movc","a","@a+dptr");
7920         break;
7921
7922     case GPOINTER:
7923         pic14_emitcode("lcall","__gptrget");
7924         break;
7925     }
7926
7927     /* if we have bitdisplacement then it fits   */
7928     /* into this byte completely or if length is */
7929     /* less than a byte                          */
7930     if ((shCnt = SPEC_BSTR(etype)) || 
7931         (SPEC_BLEN(etype) <= 8))  {
7932
7933         /* shift right acc */
7934         AccRsh(shCnt);
7935
7936         pic14_emitcode("anl","a,#0x%02x",
7937                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7938         aopPut(AOP(result),"a",offset);
7939         return ;
7940     }
7941
7942     /* bit field did not fit in a byte  */
7943     rlen = SPEC_BLEN(etype) - 8;
7944     aopPut(AOP(result),"a",offset++);
7945
7946     while (1)  {
7947
7948         switch (ptype) {
7949         case POINTER:
7950         case IPOINTER:
7951             pic14_emitcode("inc","%s",rname);
7952             pic14_emitcode("mov","a,@%s",rname);
7953             break;
7954             
7955         case PPOINTER:
7956             pic14_emitcode("inc","%s",rname);
7957             pic14_emitcode("movx","a,@%s",rname);
7958             break;
7959
7960         case FPOINTER:
7961             pic14_emitcode("inc","dptr");
7962             pic14_emitcode("movx","a,@dptr");
7963             break;
7964             
7965         case CPOINTER:
7966             pic14_emitcode("clr","a");
7967             pic14_emitcode("inc","dptr");
7968             pic14_emitcode("movc","a","@a+dptr");
7969             break;
7970             
7971         case GPOINTER:
7972             pic14_emitcode("inc","dptr");
7973             pic14_emitcode("lcall","__gptrget");
7974             break;
7975         }
7976
7977         rlen -= 8;            
7978         /* if we are done */
7979         if ( rlen <= 0 )
7980             break ;
7981         
7982         aopPut(AOP(result),"a",offset++);
7983                               
7984     }
7985     
7986     if (rlen) {
7987         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7988         aopPut(AOP(result),"a",offset);        
7989     }
7990     
7991     return ;
7992 }
7993
7994 #if 0
7995 /*-----------------------------------------------------------------*/
7996 /* genDataPointerGet - generates code when ptr offset is known     */
7997 /*-----------------------------------------------------------------*/
7998 static void genDataPointerGet (operand *left, 
7999                                operand *result, 
8000                                iCode *ic)
8001 {
8002   int size , offset = 0;
8003
8004
8005   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8006
8007
8008   /* optimization - most of the time, left and result are the same
8009    * address, but different types. for the pic code, we could omit
8010    * the following
8011    */
8012
8013   aopOp(result,ic,TRUE);
8014
8015   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8016
8017   emitpcode(POC_MOVFW, popGet(AOP(left),0));
8018
8019   size = AOP_SIZE(result);
8020
8021   while (size--) {
8022     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8023     offset++;
8024   }
8025
8026   freeAsmop(left,NULL,ic,TRUE);
8027   freeAsmop(result,NULL,ic,TRUE);
8028 }
8029 #endif
8030 /*-----------------------------------------------------------------*/
8031 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
8032 /*-----------------------------------------------------------------*/
8033 static void genNearPointerGet (operand *left, 
8034                                operand *result, 
8035                                iCode *ic)
8036 {
8037     asmop *aop = NULL;
8038     //regs *preg = NULL ;
8039     char *rname ;
8040     sym_link *rtype, *retype;
8041     sym_link *ltype = operandType(left);    
8042     //char buffer[80];
8043
8044     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8045
8046     rtype = operandType(result);
8047     retype= getSpec(rtype);
8048     
8049     aopOp(left,ic,FALSE);
8050     
8051     /* if left is rematerialisable and
8052        result is not bit variable type and
8053        the left is pointer to data space i.e
8054        lower 128 bytes of space */
8055     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8056         !IS_BITVAR(retype)         &&
8057         DCL_TYPE(ltype) == POINTER) {
8058       //genDataPointerGet (left,result,ic);
8059         return ;
8060     }
8061     
8062     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8063
8064         /* if the value is already in a pointer register
8065        then don't need anything more */
8066     if (!AOP_INPREG(AOP(left))) {
8067         /* otherwise get a free pointer register */
8068     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8069 /*
8070         aop = newAsmop(0);
8071         preg = getFreePtr(ic,&aop,FALSE);
8072         pic14_emitcode("mov","%s,%s",
8073                 preg->name,
8074                 aopGet(AOP(left),0,FALSE,TRUE));
8075         rname = preg->name ;
8076 */
8077     rname ="BAD";
8078     } else
8079         rname = aopGet(AOP(left),0,FALSE,FALSE);
8080     
8081     aopOp (result,ic,FALSE);
8082     
8083       /* if bitfield then unpack the bits */
8084     if (IS_BITVAR(retype)) 
8085         genUnpackBits (result,rname,POINTER);
8086     else {
8087         /* we have can just get the values */
8088       int size = AOP_SIZE(result);
8089       int offset = 0 ;  
8090         
8091       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8092
8093       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8094       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8095       while(size--) {
8096         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8097         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8098         if(size)
8099           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8100       }
8101 /*
8102         while (size--) {
8103             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8104
8105                 pic14_emitcode("mov","a,@%s",rname);
8106                 aopPut(AOP(result),"a",offset);
8107             } else {
8108                 sprintf(buffer,"@%s",rname);
8109                 aopPut(AOP(result),buffer,offset);
8110             }
8111             offset++ ;
8112             if (size)
8113                 pic14_emitcode("inc","%s",rname);
8114         }
8115 */
8116     }
8117
8118     /* now some housekeeping stuff */
8119     if (aop) {
8120         /* we had to allocate for this iCode */
8121     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8122         freeAsmop(NULL,aop,ic,TRUE);
8123     } else { 
8124         /* we did not allocate which means left
8125            already in a pointer register, then
8126            if size > 0 && this could be used again
8127            we have to point it back to where it 
8128            belongs */
8129     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8130         if (AOP_SIZE(result) > 1 &&
8131             !OP_SYMBOL(left)->remat &&
8132             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8133               ic->depth )) {
8134             int size = AOP_SIZE(result) - 1;
8135             while (size--)
8136                 pic14_emitcode("dec","%s",rname);
8137         }
8138     }
8139
8140     /* done */
8141     freeAsmop(left,NULL,ic,TRUE);
8142     freeAsmop(result,NULL,ic,TRUE);
8143      
8144 }
8145
8146 /*-----------------------------------------------------------------*/
8147 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8148 /*-----------------------------------------------------------------*/
8149 static void genPagedPointerGet (operand *left, 
8150                                operand *result, 
8151                                iCode *ic)
8152 {
8153     asmop *aop = NULL;
8154     regs *preg = NULL ;
8155     char *rname ;
8156     sym_link *rtype, *retype;    
8157
8158     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8159
8160     rtype = operandType(result);
8161     retype= getSpec(rtype);
8162     
8163     aopOp(left,ic,FALSE);
8164
8165   /* if the value is already in a pointer register
8166        then don't need anything more */
8167     if (!AOP_INPREG(AOP(left))) {
8168         /* otherwise get a free pointer register */
8169         aop = newAsmop(0);
8170         preg = getFreePtr(ic,&aop,FALSE);
8171         pic14_emitcode("mov","%s,%s",
8172                 preg->name,
8173                 aopGet(AOP(left),0,FALSE,TRUE));
8174         rname = preg->name ;
8175     } else
8176         rname = aopGet(AOP(left),0,FALSE,FALSE);
8177     
8178     freeAsmop(left,NULL,ic,TRUE);
8179     aopOp (result,ic,FALSE);
8180
8181     /* if bitfield then unpack the bits */
8182     if (IS_BITVAR(retype)) 
8183         genUnpackBits (result,rname,PPOINTER);
8184     else {
8185         /* we have can just get the values */
8186         int size = AOP_SIZE(result);
8187         int offset = 0 ;        
8188         
8189         while (size--) {
8190             
8191             pic14_emitcode("movx","a,@%s",rname);
8192             aopPut(AOP(result),"a",offset);
8193             
8194             offset++ ;
8195             
8196             if (size)
8197                 pic14_emitcode("inc","%s",rname);
8198         }
8199     }
8200
8201     /* now some housekeeping stuff */
8202     if (aop) {
8203         /* we had to allocate for this iCode */
8204         freeAsmop(NULL,aop,ic,TRUE);
8205     } else { 
8206         /* we did not allocate which means left
8207            already in a pointer register, then
8208            if size > 0 && this could be used again
8209            we have to point it back to where it 
8210            belongs */
8211         if (AOP_SIZE(result) > 1 &&
8212             !OP_SYMBOL(left)->remat &&
8213             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8214               ic->depth )) {
8215             int size = AOP_SIZE(result) - 1;
8216             while (size--)
8217                 pic14_emitcode("dec","%s",rname);
8218         }
8219     }
8220
8221     /* done */
8222     freeAsmop(result,NULL,ic,TRUE);
8223     
8224         
8225 }
8226
8227 /*-----------------------------------------------------------------*/
8228 /* genFarPointerGet - gget value from far space                    */
8229 /*-----------------------------------------------------------------*/
8230 static void genFarPointerGet (operand *left,
8231                               operand *result, iCode *ic)
8232 {
8233     int size, offset ;
8234     sym_link *retype = getSpec(operandType(result));
8235
8236     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8237
8238     aopOp(left,ic,FALSE);
8239
8240     /* if the operand is already in dptr 
8241     then we do nothing else we move the value to dptr */
8242     if (AOP_TYPE(left) != AOP_STR) {
8243         /* if this is remateriazable */
8244         if (AOP_TYPE(left) == AOP_IMMD)
8245             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8246         else { /* we need to get it byte by byte */
8247             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8248             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8249             if (options.model == MODEL_FLAT24)
8250             {
8251                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8252             }
8253         }
8254     }
8255     /* so dptr know contains the address */
8256     freeAsmop(left,NULL,ic,TRUE);
8257     aopOp(result,ic,FALSE);
8258
8259     /* if bit then unpack */
8260     if (IS_BITVAR(retype)) 
8261         genUnpackBits(result,"dptr",FPOINTER);
8262     else {
8263         size = AOP_SIZE(result);
8264         offset = 0 ;
8265
8266         while (size--) {
8267             pic14_emitcode("movx","a,@dptr");
8268             aopPut(AOP(result),"a",offset++);
8269             if (size)
8270                 pic14_emitcode("inc","dptr");
8271         }
8272     }
8273
8274     freeAsmop(result,NULL,ic,TRUE);
8275 }
8276 #if 0
8277 /*-----------------------------------------------------------------*/
8278 /* genCodePointerGet - get value from code space                  */
8279 /*-----------------------------------------------------------------*/
8280 static void genCodePointerGet (operand *left,
8281                                 operand *result, iCode *ic)
8282 {
8283     int size, offset ;
8284     sym_link *retype = getSpec(operandType(result));
8285
8286     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8287
8288     aopOp(left,ic,FALSE);
8289
8290     /* if the operand is already in dptr 
8291     then we do nothing else we move the value to dptr */
8292     if (AOP_TYPE(left) != AOP_STR) {
8293         /* if this is remateriazable */
8294         if (AOP_TYPE(left) == AOP_IMMD)
8295             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8296         else { /* we need to get it byte by byte */
8297             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8298             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8299             if (options.model == MODEL_FLAT24)
8300             {
8301                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8302             }
8303         }
8304     }
8305     /* so dptr know contains the address */
8306     freeAsmop(left,NULL,ic,TRUE);
8307     aopOp(result,ic,FALSE);
8308
8309     /* if bit then unpack */
8310     if (IS_BITVAR(retype)) 
8311         genUnpackBits(result,"dptr",CPOINTER);
8312     else {
8313         size = AOP_SIZE(result);
8314         offset = 0 ;
8315
8316         while (size--) {
8317             pic14_emitcode("clr","a");
8318             pic14_emitcode("movc","a,@a+dptr");
8319             aopPut(AOP(result),"a",offset++);
8320             if (size)
8321                 pic14_emitcode("inc","dptr");
8322         }
8323     }
8324
8325     freeAsmop(result,NULL,ic,TRUE);
8326 }
8327 #endif
8328 /*-----------------------------------------------------------------*/
8329 /* genGenPointerGet - gget value from generic pointer space        */
8330 /*-----------------------------------------------------------------*/
8331 static void genGenPointerGet (operand *left,
8332                               operand *result, iCode *ic)
8333 {
8334   int size, offset ;
8335   sym_link *retype = getSpec(operandType(result));
8336
8337   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8338   aopOp(left,ic,FALSE);
8339   aopOp(result,ic,FALSE);
8340
8341
8342   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8343
8344   /* if the operand is already in dptr 
8345      then we do nothing else we move the value to dptr */
8346   //  if (AOP_TYPE(left) != AOP_STR) {
8347     /* if this is remateriazable */
8348     if (AOP_TYPE(left) == AOP_IMMD) {
8349       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8350       pic14_emitcode("mov","b,#%d",pointerCode(retype));
8351     }
8352     else { /* we need to get it byte by byte */
8353
8354       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8355       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8356
8357       size = AOP_SIZE(result);
8358       offset = 0 ;
8359
8360       while(size--) {
8361         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8362         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8363         if(size)
8364           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8365       }
8366       goto release;
8367     }
8368     //}
8369   /* so dptr know contains the address */
8370
8371   /* if bit then unpack */
8372   //if (IS_BITVAR(retype)) 
8373   //  genUnpackBits(result,"dptr",GPOINTER);
8374
8375  release:
8376   freeAsmop(left,NULL,ic,TRUE);
8377   freeAsmop(result,NULL,ic,TRUE);
8378
8379 }
8380
8381 /*-----------------------------------------------------------------*/
8382 /* genConstPointerGet - get value from const generic pointer space */
8383 /*-----------------------------------------------------------------*/
8384 static void genConstPointerGet (operand *left,
8385                                 operand *result, iCode *ic)
8386 {
8387   //sym_link *retype = getSpec(operandType(result));
8388   symbol *albl = newiTempLabel(NULL);
8389   symbol *blbl = newiTempLabel(NULL);
8390   PIC_OPCODE poc;
8391
8392   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8393   aopOp(left,ic,FALSE);
8394   aopOp(result,ic,FALSE);
8395
8396
8397   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8398
8399   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8400
8401   emitpcode(POC_CALL,popGetLabel(albl->key));
8402   emitpcodePagesel(popGetLabel(blbl->key)->name); /* Must restore PCLATH before goto, without destroying W */
8403   emitpcode(POC_GOTO,popGetLabel(blbl->key));
8404   emitpLabel(albl->key);
8405
8406   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8407     
8408   emitpcode(poc,popGet(AOP(left),1));
8409   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8410   emitpcode(poc,popGet(AOP(left),0));
8411   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8412
8413   emitpLabel(blbl->key);
8414
8415   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8416
8417
8418   freeAsmop(left,NULL,ic,TRUE);
8419   freeAsmop(result,NULL,ic,TRUE);
8420
8421 }
8422 /*-----------------------------------------------------------------*/
8423 /* genPointerGet - generate code for pointer get                   */
8424 /*-----------------------------------------------------------------*/
8425 static void genPointerGet (iCode *ic)
8426 {
8427     operand *left, *result ;
8428     sym_link *type, *etype;
8429     int p_type;
8430
8431     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8432
8433     left = IC_LEFT(ic);
8434     result = IC_RESULT(ic) ;
8435
8436     /* depending on the type of pointer we need to
8437     move it to the correct pointer register */
8438     type = operandType(left);
8439     etype = getSpec(type);
8440
8441     if (IS_PTR_CONST(type))
8442       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8443
8444     /* if left is of type of pointer then it is simple */
8445     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8446         p_type = DCL_TYPE(type);
8447     else {
8448         /* we have to go by the storage class */
8449         p_type = PTR_TYPE(SPEC_OCLS(etype));
8450
8451         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8452
8453         if (SPEC_OCLS(etype)->codesp ) {
8454           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8455           //p_type = CPOINTER ; 
8456         }
8457         else
8458             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8459               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8460                /*p_type = FPOINTER ;*/ 
8461             else
8462                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8463                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8464 /*                  p_type = PPOINTER; */
8465                 else
8466                     if (SPEC_OCLS(etype) == idata )
8467                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8468 /*                      p_type = IPOINTER; */
8469                     else
8470                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8471 /*                      p_type = POINTER ; */
8472     }
8473
8474     /* now that we have the pointer type we assign
8475     the pointer values */
8476     switch (p_type) {
8477
8478     case POINTER:       
8479     case IPOINTER:
8480         genNearPointerGet (left,result,ic);
8481         break;
8482
8483     case PPOINTER:
8484         genPagedPointerGet(left,result,ic);
8485         break;
8486
8487     case FPOINTER:
8488         genFarPointerGet (left,result,ic);
8489         break;
8490
8491     case CPOINTER:
8492         genConstPointerGet (left,result,ic);
8493         //pic14_emitcodePointerGet (left,result,ic);
8494         break;
8495
8496     case GPOINTER:
8497       if (IS_PTR_CONST(type))
8498         genConstPointerGet (left,result,ic);
8499       else
8500         genGenPointerGet (left,result,ic);
8501       break;
8502     }
8503
8504 }
8505
8506 /*-----------------------------------------------------------------*/
8507 /* genPackBits - generates code for packed bit storage             */
8508 /*-----------------------------------------------------------------*/
8509 static void genPackBits (sym_link    *etype ,
8510                          operand *right ,
8511                          char *rname, int p_type)
8512 {
8513     int shCount = 0 ;
8514     int offset = 0  ;
8515     int rLen = 0 ;
8516     int blen, bstr ;   
8517     char *l ;
8518
8519     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8520     blen = SPEC_BLEN(etype);
8521     bstr = SPEC_BSTR(etype);
8522
8523     l = aopGet(AOP(right),offset++,FALSE,FALSE);
8524     MOVA(l);   
8525
8526     /* if the bit lenth is less than or    */
8527     /* it exactly fits a byte then         */
8528     if (SPEC_BLEN(etype) <= 8 )  {
8529         shCount = SPEC_BSTR(etype) ;
8530
8531         /* shift left acc */
8532         AccLsh(shCount);
8533
8534         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8535
8536
8537             switch (p_type) {
8538                 case POINTER:
8539                     pic14_emitcode ("mov","b,a");
8540                     pic14_emitcode("mov","a,@%s",rname);
8541                     break;
8542
8543                 case FPOINTER:
8544                     pic14_emitcode ("mov","b,a");
8545                     pic14_emitcode("movx","a,@dptr");
8546                     break;
8547
8548                 case GPOINTER:
8549                     pic14_emitcode ("push","b");
8550                     pic14_emitcode ("push","acc");
8551                     pic14_emitcode ("lcall","__gptrget");
8552                     pic14_emitcode ("pop","b");
8553                     break;
8554             }
8555
8556             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8557                       ((unsigned char)(0xFF << (blen+bstr)) | 
8558                        (unsigned char)(0xFF >> (8-bstr)) ) );
8559             pic14_emitcode ("orl","a,b");
8560             if (p_type == GPOINTER)
8561                 pic14_emitcode("pop","b");
8562         }
8563     }
8564
8565     switch (p_type) {
8566         case POINTER:
8567             pic14_emitcode("mov","@%s,a",rname);
8568             break;
8569
8570         case FPOINTER:
8571             pic14_emitcode("movx","@dptr,a");
8572             break;
8573
8574         case GPOINTER:
8575             DEBUGpic14_emitcode(";lcall","__gptrput");
8576             break;
8577     }
8578
8579     /* if we r done */
8580     if ( SPEC_BLEN(etype) <= 8 )
8581         return ;
8582
8583     pic14_emitcode("inc","%s",rname);
8584     rLen = SPEC_BLEN(etype) ;     
8585
8586     /* now generate for lengths greater than one byte */
8587     while (1) {
8588
8589         l = aopGet(AOP(right),offset++,FALSE,TRUE);
8590
8591         rLen -= 8 ;
8592         if (rLen <= 0 )
8593             break ;
8594
8595         switch (p_type) {
8596             case POINTER:
8597                 if (*l == '@') {
8598                     MOVA(l);
8599                     pic14_emitcode("mov","@%s,a",rname);
8600                 } else
8601                     pic14_emitcode("mov","@%s,%s",rname,l);
8602                 break;
8603
8604             case FPOINTER:
8605                 MOVA(l);
8606                 pic14_emitcode("movx","@dptr,a");
8607                 break;
8608
8609             case GPOINTER:
8610                 MOVA(l);
8611                 DEBUGpic14_emitcode(";lcall","__gptrput");
8612                 break;  
8613         }   
8614         pic14_emitcode ("inc","%s",rname);
8615     }
8616
8617     MOVA(l);
8618
8619     /* last last was not complete */
8620     if (rLen)   {
8621         /* save the byte & read byte */
8622         switch (p_type) {
8623             case POINTER:
8624                 pic14_emitcode ("mov","b,a");
8625                 pic14_emitcode("mov","a,@%s",rname);
8626                 break;
8627
8628             case FPOINTER:
8629                 pic14_emitcode ("mov","b,a");
8630                 pic14_emitcode("movx","a,@dptr");
8631                 break;
8632
8633             case GPOINTER:
8634                 pic14_emitcode ("push","b");
8635                 pic14_emitcode ("push","acc");
8636                 pic14_emitcode ("lcall","__gptrget");
8637                 pic14_emitcode ("pop","b");
8638                 break;
8639         }
8640
8641         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8642         pic14_emitcode ("orl","a,b");
8643     }
8644
8645     if (p_type == GPOINTER)
8646         pic14_emitcode("pop","b");
8647
8648     switch (p_type) {
8649
8650     case POINTER:
8651         pic14_emitcode("mov","@%s,a",rname);
8652         break;
8653         
8654     case FPOINTER:
8655         pic14_emitcode("movx","@dptr,a");
8656         break;
8657         
8658     case GPOINTER:
8659         DEBUGpic14_emitcode(";lcall","__gptrput");
8660         break;                  
8661     }
8662 }
8663 /*-----------------------------------------------------------------*/
8664 /* genDataPointerSet - remat pointer to data space                 */
8665 /*-----------------------------------------------------------------*/
8666 static void genDataPointerSet(operand *right,
8667                               operand *result,
8668                               iCode *ic)
8669 {
8670     int size, offset = 0 ;
8671     char *l, buffer[256];
8672
8673     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8674     aopOp(right,ic,FALSE);
8675     
8676     l = aopGet(AOP(result),0,FALSE,TRUE);
8677     size = AOP_SIZE(right);
8678 /*
8679     if ( AOP_TYPE(result) == AOP_PCODE) {
8680       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8681               AOP(result)->aopu.pcop->name,
8682               PCOI(AOP(result)->aopu.pcop)->offset);
8683     }
8684 */
8685
8686     // tsd, was l+1 - the underline `_' prefix was being stripped
8687     while (size--) {
8688       if (offset) {
8689         sprintf(buffer,"(%s + %d)",l,offset);
8690         fprintf(stderr,"oops  %s\n",buffer);
8691       } else
8692         sprintf(buffer,"%s",l);
8693
8694         if (AOP_TYPE(right) == AOP_LIT) {
8695           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8696           lit = lit >> (8*offset);
8697           if(lit&0xff) {
8698             pic14_emitcode("movlw","%d",lit);
8699             pic14_emitcode("movwf","%s",buffer);
8700
8701             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8702             //emitpcode(POC_MOVWF, popRegFromString(buffer));
8703             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8704
8705           } else {
8706             pic14_emitcode("clrf","%s",buffer);
8707             //emitpcode(POC_CLRF, popRegFromString(buffer));
8708             emitpcode(POC_CLRF, popGet(AOP(result),0));
8709           }
8710         }else {
8711           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8712           pic14_emitcode("movwf","%s",buffer);
8713
8714           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8715           //emitpcode(POC_MOVWF, popRegFromString(buffer));
8716           emitpcode(POC_MOVWF, popGet(AOP(result),0));
8717
8718         }
8719
8720         offset++;
8721     }
8722
8723     freeAsmop(right,NULL,ic,TRUE);
8724     freeAsmop(result,NULL,ic,TRUE);
8725 }
8726
8727 /*-----------------------------------------------------------------*/
8728 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8729 /*-----------------------------------------------------------------*/
8730 static void genNearPointerSet (operand *right,
8731                                operand *result, 
8732                                iCode *ic)
8733 {
8734   asmop *aop = NULL;
8735   char *l;
8736   sym_link *retype;
8737   sym_link *ptype = operandType(result);
8738
8739     
8740   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8741   retype= getSpec(operandType(right));
8742
8743   aopOp(result,ic,FALSE);
8744
8745     
8746   /* if the result is rematerializable &
8747      in data space & not a bit variable */
8748   //if (AOP_TYPE(result) == AOP_IMMD &&
8749   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8750       DCL_TYPE(ptype) == POINTER   &&
8751       !IS_BITVAR(retype)) {
8752     genDataPointerSet (right,result,ic);
8753     freeAsmop(result,NULL,ic,TRUE);
8754     return;
8755   }
8756
8757   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8758   aopOp(right,ic,FALSE);
8759   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8760
8761   /* if the value is already in a pointer register
8762      then don't need anything more */
8763   if (!AOP_INPREG(AOP(result))) {
8764     /* otherwise get a free pointer register */
8765     //aop = newAsmop(0);
8766     //preg = getFreePtr(ic,&aop,FALSE);
8767     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8768     //pic14_emitcode("mov","%s,%s",
8769     //         preg->name,
8770     //         aopGet(AOP(result),0,FALSE,TRUE));
8771     //rname = preg->name ;
8772     //pic14_emitcode("movwf","fsr");
8773     emitpcode(POC_MOVFW, popGet(AOP(result),0));
8774     emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8775     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8776     emitpcode(POC_MOVWF, popCopyReg(&pc_indf));
8777     goto release;
8778
8779   }// else
8780   //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8781
8782
8783   /* if bitfield then unpack the bits */
8784   if (IS_BITVAR(retype)) {
8785     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8786            "The programmer is obviously confused");
8787     //genPackBits (retype,right,rname,POINTER);
8788     exit(1);
8789   }
8790   else {
8791     /* we have can just get the values */
8792     int size = AOP_SIZE(right);
8793     int offset = 0 ;    
8794
8795     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8796     while (size--) {
8797       l = aopGet(AOP(right),offset,FALSE,TRUE);
8798       if (*l == '@' ) {
8799         //MOVA(l);
8800         //pic14_emitcode("mov","@%s,a",rname);
8801         pic14_emitcode("movf","indf,w ;1");
8802       } else {
8803
8804         if (AOP_TYPE(right) == AOP_LIT) {
8805           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8806           if(lit) {
8807             pic14_emitcode("movlw","%s",l);
8808             pic14_emitcode("movwf","indf ;2");
8809           } else 
8810             pic14_emitcode("clrf","indf");
8811         }else {
8812           pic14_emitcode("movf","%s,w",l);
8813           pic14_emitcode("movwf","indf ;2");
8814         }
8815         //pic14_emitcode("mov","@%s,%s",rname,l);
8816       }
8817       if (size)
8818         pic14_emitcode("incf","fsr,f ;3");
8819       //pic14_emitcode("inc","%s",rname);
8820       offset++;
8821     }
8822   }
8823
8824   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8825   /* now some housekeeping stuff */
8826   if (aop) {
8827     /* we had to allocate for this iCode */
8828     freeAsmop(NULL,aop,ic,TRUE);
8829   } else { 
8830     /* we did not allocate which means left
8831        already in a pointer register, then
8832        if size > 0 && this could be used again
8833        we have to point it back to where it 
8834        belongs */
8835     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8836     if (AOP_SIZE(right) > 1 &&
8837         !OP_SYMBOL(result)->remat &&
8838         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8839           ic->depth )) {
8840       int size = AOP_SIZE(right) - 1;
8841       while (size--)
8842         pic14_emitcode("decf","fsr,f");
8843       //pic14_emitcode("dec","%s",rname);
8844     }
8845   }
8846
8847   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8848   /* done */
8849  release:
8850   freeAsmop(right,NULL,ic,TRUE);
8851   freeAsmop(result,NULL,ic,TRUE);
8852 }
8853
8854 /*-----------------------------------------------------------------*/
8855 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8856 /*-----------------------------------------------------------------*/
8857 static void genPagedPointerSet (operand *right,
8858                                operand *result, 
8859                                iCode *ic)
8860 {
8861     asmop *aop = NULL;
8862     regs *preg = NULL ;
8863     char *rname , *l;
8864     sym_link *retype;
8865        
8866     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8867
8868     retype= getSpec(operandType(right));
8869     
8870     aopOp(result,ic,FALSE);
8871     
8872     /* if the value is already in a pointer register
8873        then don't need anything more */
8874     if (!AOP_INPREG(AOP(result))) {
8875         /* otherwise get a free pointer register */
8876         aop = newAsmop(0);
8877         preg = getFreePtr(ic,&aop,FALSE);
8878         pic14_emitcode("mov","%s,%s",
8879                 preg->name,
8880                 aopGet(AOP(result),0,FALSE,TRUE));
8881         rname = preg->name ;
8882     } else
8883         rname = aopGet(AOP(result),0,FALSE,FALSE);
8884     
8885     freeAsmop(result,NULL,ic,TRUE);
8886     aopOp (right,ic,FALSE);
8887
8888     /* if bitfield then unpack the bits */
8889     if (IS_BITVAR(retype)) 
8890         genPackBits (retype,right,rname,PPOINTER);
8891     else {
8892         /* we have can just get the values */
8893         int size = AOP_SIZE(right);
8894         int offset = 0 ;        
8895         
8896         while (size--) {
8897             l = aopGet(AOP(right),offset,FALSE,TRUE);
8898             
8899             MOVA(l);
8900             pic14_emitcode("movx","@%s,a",rname);
8901
8902             if (size)
8903                 pic14_emitcode("inc","%s",rname);
8904
8905             offset++;
8906         }
8907     }
8908     
8909     /* now some housekeeping stuff */
8910     if (aop) {
8911         /* we had to allocate for this iCode */
8912         freeAsmop(NULL,aop,ic,TRUE);
8913     } else { 
8914         /* we did not allocate which means left
8915            already in a pointer register, then
8916            if size > 0 && this could be used again
8917            we have to point it back to where it 
8918            belongs */
8919         if (AOP_SIZE(right) > 1 &&
8920             !OP_SYMBOL(result)->remat &&
8921             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8922               ic->depth )) {
8923             int size = AOP_SIZE(right) - 1;
8924             while (size--)
8925                 pic14_emitcode("dec","%s",rname);
8926         }
8927     }
8928
8929     /* done */
8930     freeAsmop(right,NULL,ic,TRUE);
8931     
8932         
8933 }
8934
8935 /*-----------------------------------------------------------------*/
8936 /* genFarPointerSet - set value from far space                     */
8937 /*-----------------------------------------------------------------*/
8938 static void genFarPointerSet (operand *right,
8939                               operand *result, iCode *ic)
8940 {
8941     int size, offset ;
8942     sym_link *retype = getSpec(operandType(right));
8943
8944     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8945     aopOp(result,ic,FALSE);
8946
8947     /* if the operand is already in dptr 
8948     then we do nothing else we move the value to dptr */
8949     if (AOP_TYPE(result) != AOP_STR) {
8950         /* if this is remateriazable */
8951         if (AOP_TYPE(result) == AOP_IMMD)
8952             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8953         else { /* we need to get it byte by byte */
8954             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8955             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8956             if (options.model == MODEL_FLAT24)
8957             {
8958                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8959             }
8960         }
8961     }
8962     /* so dptr know contains the address */
8963     freeAsmop(result,NULL,ic,TRUE);
8964     aopOp(right,ic,FALSE);
8965
8966     /* if bit then unpack */
8967     if (IS_BITVAR(retype)) 
8968         genPackBits(retype,right,"dptr",FPOINTER);
8969     else {
8970         size = AOP_SIZE(right);
8971         offset = 0 ;
8972
8973         while (size--) {
8974             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8975             MOVA(l);
8976             pic14_emitcode("movx","@dptr,a");
8977             if (size)
8978                 pic14_emitcode("inc","dptr");
8979         }
8980     }
8981
8982     freeAsmop(right,NULL,ic,TRUE);
8983 }
8984
8985 /*-----------------------------------------------------------------*/
8986 /* genGenPointerSet - set value from generic pointer space         */
8987 /*-----------------------------------------------------------------*/
8988 static void genGenPointerSet (operand *right,
8989                               operand *result, iCode *ic)
8990 {
8991   int size, offset ;
8992   sym_link *retype = getSpec(operandType(right));
8993
8994   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8995
8996   aopOp(result,ic,FALSE);
8997   aopOp(right,ic,FALSE);
8998   size = AOP_SIZE(right);
8999
9000   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9001
9002   /* if the operand is already in dptr 
9003      then we do nothing else we move the value to dptr */
9004   if (AOP_TYPE(result) != AOP_STR) {
9005     /* if this is remateriazable */
9006     if (AOP_TYPE(result) == AOP_IMMD) {
9007       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9008       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9009     }
9010     else { /* we need to get it byte by byte */
9011       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
9012       size = AOP_SIZE(right);
9013       offset = 0 ;
9014
9015       /* hack hack! see if this the FSR. If so don't load W */
9016       if(AOP_TYPE(right) != AOP_ACC) {
9017
9018
9019         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9020         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9021
9022         if(AOP_SIZE(result) > 1) {
9023           emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9024           emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9025           emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9026
9027         }
9028
9029         //if(size==2)
9030         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
9031         //if(size==4) {
9032         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
9033         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
9034         //}
9035
9036         while(size--) {
9037           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
9038           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9039           
9040           if(size)
9041             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9042         }
9043
9044
9045         goto release;
9046       } 
9047
9048       if(aopIdx(AOP(result),0) != 4) {
9049
9050         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9051         goto release;
9052       }
9053
9054       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9055       goto release;
9056
9057     }
9058   }
9059   /* so dptr know contains the address */
9060
9061
9062   /* if bit then unpack */
9063   if (IS_BITVAR(retype)) 
9064     genPackBits(retype,right,"dptr",GPOINTER);
9065   else {
9066     size = AOP_SIZE(right);
9067     offset = 0 ;
9068
9069   DEBUGpic14_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9070
9071     while (size--) {
9072
9073       emitpcode(POC_MOVFW,popGet(AOP(result),offset));
9074       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9075
9076       if (AOP_TYPE(right) == AOP_LIT) 
9077         emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9078       else
9079         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9080
9081       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9082
9083       offset++;
9084     }
9085   }
9086
9087  release:
9088   freeAsmop(right,NULL,ic,TRUE);
9089   freeAsmop(result,NULL,ic,TRUE);
9090 }
9091
9092 /*-----------------------------------------------------------------*/
9093 /* genPointerSet - stores the value into a pointer location        */
9094 /*-----------------------------------------------------------------*/
9095 static void genPointerSet (iCode *ic)
9096 {    
9097     operand *right, *result ;
9098     sym_link *type, *etype;
9099     int p_type;
9100
9101     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9102
9103     right = IC_RIGHT(ic);
9104     result = IC_RESULT(ic) ;
9105
9106     /* depending on the type of pointer we need to
9107     move it to the correct pointer register */
9108     type = operandType(result);
9109     etype = getSpec(type);
9110     /* if left is of type of pointer then it is simple */
9111     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9112         p_type = DCL_TYPE(type);
9113     }
9114     else {
9115         /* we have to go by the storage class */
9116         p_type = PTR_TYPE(SPEC_OCLS(etype));
9117
9118 /*      if (SPEC_OCLS(etype)->codesp ) { */
9119 /*          p_type = CPOINTER ;  */
9120 /*      } */
9121 /*      else */
9122 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9123 /*              p_type = FPOINTER ; */
9124 /*          else */
9125 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9126 /*                  p_type = PPOINTER ; */
9127 /*              else */
9128 /*                  if (SPEC_OCLS(etype) == idata ) */
9129 /*                      p_type = IPOINTER ; */
9130 /*                  else */
9131 /*                      p_type = POINTER ; */
9132     }
9133
9134     /* now that we have the pointer type we assign
9135     the pointer values */
9136     switch (p_type) {
9137
9138     case POINTER:
9139     case IPOINTER:
9140         genNearPointerSet (right,result,ic);
9141         break;
9142
9143     case PPOINTER:
9144         genPagedPointerSet (right,result,ic);
9145         break;
9146
9147     case FPOINTER:
9148         genFarPointerSet (right,result,ic);
9149         break;
9150
9151     case GPOINTER:
9152         genGenPointerSet (right,result,ic);
9153         break;
9154
9155     default:
9156       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9157               "genPointerSet: illegal pointer type");
9158     }
9159 }
9160
9161 /*-----------------------------------------------------------------*/
9162 /* genIfx - generate code for Ifx statement                        */
9163 /*-----------------------------------------------------------------*/
9164 static void genIfx (iCode *ic, iCode *popIc)
9165 {
9166   operand *cond = IC_COND(ic);
9167   int isbit =0;
9168
9169   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9170
9171   aopOp(cond,ic,FALSE);
9172
9173   /* get the value into acc */
9174   if (AOP_TYPE(cond) != AOP_CRY)
9175     pic14_toBoolean(cond);
9176   else
9177     isbit = 1;
9178   /* the result is now in the accumulator */
9179   freeAsmop(cond,NULL,ic,TRUE);
9180
9181   /* if there was something to be popped then do it */
9182   if (popIc)
9183     genIpop(popIc);
9184
9185   /* if the condition is  a bit variable */
9186   if (isbit && IS_ITEMP(cond) && 
9187       SPIL_LOC(cond)) {
9188     genIfxJump(ic,SPIL_LOC(cond)->rname);
9189     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9190   }
9191   else {
9192     if (isbit && !IS_ITEMP(cond))
9193       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9194     else
9195       genIfxJump(ic,"a");
9196   }
9197   ic->generated = 1;
9198
9199 }
9200
9201 /*-----------------------------------------------------------------*/
9202 /* genAddrOf - generates code for address of                       */
9203 /*-----------------------------------------------------------------*/
9204 static void genAddrOf (iCode *ic)
9205 {
9206   operand *right, *result, *left;
9207   int size, offset ;
9208
9209   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9210
9211
9212   //aopOp(IC_RESULT(ic),ic,FALSE);
9213
9214   aopOp((left=IC_LEFT(ic)),ic,FALSE);
9215   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9216   aopOp((result=IC_RESULT(ic)),ic,TRUE);
9217
9218   DEBUGpic14_AopType(__LINE__,left,right,result);
9219
9220   size = AOP_SIZE(IC_RESULT(ic));
9221   offset = 0;
9222
9223   while (size--) {
9224     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9225     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9226     offset++;
9227   }
9228
9229   freeAsmop(left,NULL,ic,FALSE);
9230   freeAsmop(result,NULL,ic,TRUE);
9231
9232 }
9233
9234 #if 0
9235 /*-----------------------------------------------------------------*/
9236 /* genFarFarAssign - assignment when both are in far space         */
9237 /*-----------------------------------------------------------------*/
9238 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9239 {
9240     int size = AOP_SIZE(right);
9241     int offset = 0;
9242     char *l ;
9243     /* first push the right side on to the stack */
9244     while (size--) {
9245         l = aopGet(AOP(right),offset++,FALSE,FALSE);
9246         MOVA(l);
9247         pic14_emitcode ("push","acc");
9248     }
9249     
9250     freeAsmop(right,NULL,ic,FALSE);
9251     /* now assign DPTR to result */
9252     aopOp(result,ic,FALSE);
9253     size = AOP_SIZE(result);
9254     while (size--) {
9255         pic14_emitcode ("pop","acc");
9256         aopPut(AOP(result),"a",--offset);
9257     }
9258     freeAsmop(result,NULL,ic,FALSE);
9259         
9260 }
9261 #endif
9262
9263 /*-----------------------------------------------------------------*/
9264 /* genAssign - generate code for assignment                        */
9265 /*-----------------------------------------------------------------*/
9266 static void genAssign (iCode *ic)
9267 {
9268   operand *result, *right;
9269   int size, offset,know_W;
9270   unsigned long lit = 0L;
9271
9272   result = IC_RESULT(ic);
9273   right  = IC_RIGHT(ic) ;
9274
9275   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9276
9277   /* if they are the same */
9278   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9279     return ;
9280
9281   aopOp(right,ic,FALSE);
9282   aopOp(result,ic,TRUE);
9283
9284   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9285
9286   /* if they are the same registers */
9287   if (pic14_sameRegs(AOP(right),AOP(result)))
9288     goto release;
9289
9290   /* if the result is a bit */
9291   if (AOP_TYPE(result) == AOP_CRY) {
9292
9293     /* if the right size is a literal then
9294        we know what the value is */
9295     if (AOP_TYPE(right) == AOP_LIT) {
9296           
9297       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9298                   popGet(AOP(result),0));
9299
9300       if (((int) operandLitValue(right))) 
9301         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9302                        AOP(result)->aopu.aop_dir,
9303                        AOP(result)->aopu.aop_dir);
9304       else
9305         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9306                        AOP(result)->aopu.aop_dir,
9307                        AOP(result)->aopu.aop_dir);
9308       goto release;
9309     }
9310
9311     /* the right is also a bit variable */
9312     if (AOP_TYPE(right) == AOP_CRY) {
9313       emitpcode(POC_BCF,    popGet(AOP(result),0));
9314       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9315       emitpcode(POC_BSF,    popGet(AOP(result),0));
9316
9317       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9318                      AOP(result)->aopu.aop_dir,
9319                      AOP(result)->aopu.aop_dir);
9320       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9321                      AOP(right)->aopu.aop_dir,
9322                      AOP(right)->aopu.aop_dir);
9323       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9324                      AOP(result)->aopu.aop_dir,
9325                      AOP(result)->aopu.aop_dir);
9326       goto release ;
9327     }
9328
9329     /* we need to or */
9330     emitpcode(POC_BCF,    popGet(AOP(result),0));
9331     pic14_toBoolean(right);
9332     emitSKPZ;
9333     emitpcode(POC_BSF,    popGet(AOP(result),0));
9334     //aopPut(AOP(result),"a",0);
9335     goto release ;
9336   }
9337
9338   /* bit variables done */
9339   /* general case */
9340   size = AOP_SIZE(result);
9341   offset = 0 ;
9342   if(AOP_TYPE(right) == AOP_LIT)
9343     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9344
9345   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9346   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9347     if(aopIdx(AOP(result),0) == 4) {
9348   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9349       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9350       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9351       goto release;
9352     } else
9353       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9354   }
9355
9356   know_W=-1;
9357   while (size--) {
9358   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9359     if(AOP_TYPE(right) == AOP_LIT) {
9360       if(lit&0xff) {
9361         if(know_W != (int)(lit&0xff))
9362           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9363         know_W = lit&0xff;
9364         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9365       } else
9366         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9367
9368       lit >>= 8;
9369
9370     } else if (AOP_TYPE(right) == AOP_CRY) {
9371       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9372       if(offset == 0) {
9373         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9374         emitpcode(POC_INCF, popGet(AOP(result),0));
9375       }
9376     } else {
9377       mov2w (AOP(right), offset);
9378       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9379     }
9380             
9381     offset++;
9382   }
9383
9384     
9385  release:
9386   freeAsmop (right,NULL,ic,FALSE);
9387   freeAsmop (result,NULL,ic,TRUE);
9388 }   
9389
9390 /*-----------------------------------------------------------------*/
9391 /* genJumpTab - genrates code for jump table                       */
9392 /*-----------------------------------------------------------------*/
9393 static void genJumpTab (iCode *ic)
9394 {
9395     symbol *jtab;
9396     char *l;
9397
9398     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9399
9400     aopOp(IC_JTCOND(ic),ic,FALSE);
9401     /* get the condition into accumulator */
9402     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9403     MOVA(l);
9404     /* multiply by three */
9405     pic14_emitcode("add","a,acc");
9406     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9407
9408     jtab = newiTempLabel(NULL);
9409     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9410     pic14_emitcode("jmp","@a+dptr");
9411     pic14_emitcode("","%05d_DS_:",jtab->key+100);
9412
9413     emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9414     emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9415     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9416     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9417     emitSKPNC;
9418     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9419     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9420     emitpLabel(jtab->key);
9421
9422     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9423
9424     /* now generate the jump labels */
9425     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9426          jtab = setNextItem(IC_JTLABELS(ic))) {
9427         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9428         emitpcode(POC_GOTO,popGetLabel(jtab->key));
9429         
9430     }
9431
9432 }
9433
9434 /*-----------------------------------------------------------------*/
9435 /* genMixedOperation - gen code for operators between mixed types  */
9436 /*-----------------------------------------------------------------*/
9437 /*
9438   TSD - Written for the PIC port - but this unfortunately is buggy.
9439   This routine is good in that it is able to efficiently promote 
9440   types to different (larger) sizes. Unfortunately, the temporary
9441   variables that are optimized out by this routine are sometimes
9442   used in other places. So until I know how to really parse the 
9443   iCode tree, I'm going to not be using this routine :(.
9444 */
9445 static int genMixedOperation (iCode *ic)
9446 {
9447 #if 0
9448   operand *result = IC_RESULT(ic);
9449   sym_link *ctype = operandType(IC_LEFT(ic));
9450   operand *right = IC_RIGHT(ic);
9451   int ret = 0;
9452   int big,small;
9453   int offset;
9454
9455   iCode *nextic;
9456   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9457
9458   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9459
9460   nextic = ic->next;
9461   if(!nextic)
9462     return 0;
9463
9464   nextright = IC_RIGHT(nextic);
9465   nextleft  = IC_LEFT(nextic);
9466   nextresult = IC_RESULT(nextic);
9467
9468   aopOp(right,ic,FALSE);
9469   aopOp(result,ic,FALSE);
9470   aopOp(nextright,  nextic, FALSE);
9471   aopOp(nextleft,   nextic, FALSE);
9472   aopOp(nextresult, nextic, FALSE);
9473
9474   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9475
9476     operand *t = right;
9477     right = nextright;
9478     nextright = t; 
9479
9480     pic14_emitcode(";remove right +","");
9481
9482   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9483 /*
9484     operand *t = right;
9485     right = nextleft;
9486     nextleft = t; 
9487 */
9488     pic14_emitcode(";remove left +","");
9489   } else
9490     return 0;
9491
9492   big = AOP_SIZE(nextleft);
9493   small = AOP_SIZE(nextright);
9494
9495   switch(nextic->op) {
9496
9497   case '+':
9498     pic14_emitcode(";optimize a +","");
9499     /* if unsigned or not an integral type */
9500     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9501       pic14_emitcode(";add a bit to something","");
9502     } else {
9503
9504       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9505
9506       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9507         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9508         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9509       } else
9510         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9511
9512       offset = 0;
9513       while(--big) {
9514
9515         offset++;
9516
9517         if(--small) {
9518           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9519             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9520             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9521           }
9522
9523           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9524           emitSKPNC;
9525           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9526                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9527                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9528           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9529           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9530
9531         } else {
9532           pic14_emitcode("rlf","known_zero,w");
9533
9534           /*
9535             if right is signed
9536               btfsc  right,7
9537                addlw ff
9538           */
9539           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9540             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9541             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9542           } else {
9543             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9544           }
9545         }
9546       }
9547       ret = 1;
9548     }
9549   }
9550   ret = 1;
9551
9552 release:
9553   freeAsmop(right,NULL,ic,TRUE);
9554   freeAsmop(result,NULL,ic,TRUE);
9555   freeAsmop(nextright,NULL,ic,TRUE);
9556   freeAsmop(nextleft,NULL,ic,TRUE);
9557   if(ret)
9558     nextic->generated = 1;
9559
9560   return ret;
9561 #else
9562   return 0;
9563 #endif
9564 }
9565 /*-----------------------------------------------------------------*/
9566 /* genCast - gen code for casting                                  */
9567 /*-----------------------------------------------------------------*/
9568 static void genCast (iCode *ic)
9569 {
9570     operand *result = IC_RESULT(ic);
9571     sym_link *ctype = operandType(IC_LEFT(ic));
9572     sym_link *rtype = operandType(IC_RIGHT(ic));
9573     operand *right = IC_RIGHT(ic);
9574     int size, offset ;
9575
9576     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9577     /* if they are equivalent then do nothing */
9578     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9579         return ;
9580
9581     aopOp(right,ic,FALSE) ;
9582     aopOp(result,ic,FALSE);
9583
9584     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9585
9586     /* if the result is a bit */
9587     if (AOP_TYPE(result) == AOP_CRY) {
9588         /* if the right size is a literal then
9589         we know what the value is */
9590       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9591         if (AOP_TYPE(right) == AOP_LIT) {
9592
9593           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9594                       popGet(AOP(result),0));
9595
9596             if (((int) operandLitValue(right))) 
9597               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9598                        AOP(result)->aopu.aop_dir,
9599                        AOP(result)->aopu.aop_dir);
9600             else
9601               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9602                        AOP(result)->aopu.aop_dir,
9603                        AOP(result)->aopu.aop_dir);
9604
9605             goto release;
9606         }
9607
9608         /* the right is also a bit variable */
9609         if (AOP_TYPE(right) == AOP_CRY) {
9610
9611           emitCLRC;
9612           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9613
9614           pic14_emitcode("clrc","");
9615           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9616                    AOP(right)->aopu.aop_dir,
9617                    AOP(right)->aopu.aop_dir);
9618             aopPut(AOP(result),"c",0);
9619             goto release ;
9620         }
9621
9622         /* we need to or */
9623         if (AOP_TYPE(right) == AOP_REG) {
9624           emitpcode(POC_BCF,    popGet(AOP(result),0));
9625           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9626           emitpcode(POC_BSF,    popGet(AOP(result),0));
9627         }
9628         pic14_toBoolean(right);
9629         aopPut(AOP(result),"a",0);
9630         goto release ;
9631     }
9632
9633     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9634       int offset = 1;
9635       size = AOP_SIZE(result);
9636
9637       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9638
9639       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9640       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9641       emitpcode(POC_INCF,   popGet(AOP(result),0));
9642
9643       while (size--)
9644         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9645
9646       goto release;
9647     }
9648
9649     /* if they are the same size : or less */
9650     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9651
9652         /* if they are in the same place */
9653       if (pic14_sameRegs(AOP(right),AOP(result)))
9654         goto release;
9655
9656       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9657       if (IS_PTR_CONST(rtype))
9658         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9659       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9660         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9661
9662       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9663         emitpcode(POC_MOVLW, popGet(AOP(right),0));
9664         emitpcode(POC_MOVWF, popGet(AOP(result),0));
9665         emitpcode(POC_MOVLW, popGet(AOP(right),1));
9666         emitpcode(POC_MOVWF, popGet(AOP(result),1));
9667         if(AOP_SIZE(result) <2)
9668           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9669
9670       } else {
9671
9672         /* if they in different places then copy */
9673         size = AOP_SIZE(result);
9674         offset = 0 ;
9675         while (size--) {
9676           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9677           emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9678
9679           //aopPut(AOP(result),
9680           // aopGet(AOP(right),offset,FALSE,FALSE),
9681           // offset);
9682
9683           offset++;
9684         }
9685       }
9686       goto release;
9687     }
9688
9689
9690     /* if the result is of type pointer */
9691     if (IS_PTR(ctype)) {
9692
9693         int p_type;
9694         sym_link *type = operandType(right);
9695         sym_link *etype = getSpec(type);
9696       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9697
9698         /* pointer to generic pointer */
9699         if (IS_GENPTR(ctype)) {
9700             char *l = zero;
9701             
9702             if (IS_PTR(type)) 
9703                 p_type = DCL_TYPE(type);
9704             else {
9705                 /* we have to go by the storage class */
9706                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9707
9708 /*              if (SPEC_OCLS(etype)->codesp )  */
9709 /*                  p_type = CPOINTER ;  */
9710 /*              else */
9711 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9712 /*                      p_type = FPOINTER ; */
9713 /*                  else */
9714 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9715 /*                          p_type = PPOINTER; */
9716 /*                      else */
9717 /*                          if (SPEC_OCLS(etype) == idata ) */
9718 /*                              p_type = IPOINTER ; */
9719 /*                          else */
9720 /*                              p_type = POINTER ; */
9721             }
9722                 
9723             /* the first two bytes are known */
9724       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9725             size = GPTRSIZE - 1; 
9726             offset = 0 ;
9727             while (size--) {
9728               if(offset < AOP_SIZE(right)) {
9729       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9730                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9731                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9732                   emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9733                   emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9734                 } else { 
9735                   aopPut(AOP(result),
9736                          aopGet(AOP(right),offset,FALSE,FALSE),
9737                          offset);
9738                 }
9739               } else 
9740                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9741               offset++;
9742             }
9743             /* the last byte depending on type */
9744             switch (p_type) {
9745             case IPOINTER:
9746             case POINTER:
9747                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9748                 break;
9749             case FPOINTER:
9750               pic14_emitcode(";BUG!? ","%d",__LINE__);
9751                 l = one;
9752                 break;
9753             case CPOINTER:
9754               pic14_emitcode(";BUG!? ","%d",__LINE__);
9755                 l = "#0x02";
9756                 break;                          
9757             case PPOINTER:
9758               pic14_emitcode(";BUG!? ","%d",__LINE__);
9759                 l = "#0x03";
9760                 break;
9761                 
9762             default:
9763                 /* this should never happen */
9764                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9765                        "got unknown pointer type");
9766                 exit(1);
9767             }
9768             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9769             goto release ;
9770         }
9771         
9772         /* just copy the pointers */
9773         size = AOP_SIZE(result);
9774         offset = 0 ;
9775         while (size--) {
9776             aopPut(AOP(result),
9777                    aopGet(AOP(right),offset,FALSE,FALSE),
9778                    offset);
9779             offset++;
9780         }
9781         goto release ;
9782     }
9783     
9784
9785
9786     /* so we now know that the size of destination is greater
9787     than the size of the source.
9788     Now, if the next iCode is an operator then we might be
9789     able to optimize the operation without performing a cast.
9790     */
9791     if(genMixedOperation(ic))
9792       goto release;
9793
9794     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9795     
9796     /* we move to result for the size of source */
9797     size = AOP_SIZE(right);
9798     offset = 0 ;
9799     while (size--) {
9800       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9801       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9802       offset++;
9803     }
9804
9805     /* now depending on the sign of the destination */
9806     size = AOP_SIZE(result) - AOP_SIZE(right);
9807     /* if unsigned or not an integral type */
9808     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9809       while (size--)
9810         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9811     } else {
9812       /* we need to extend the sign :{ */
9813
9814       if(size == 1) {
9815         /* Save one instruction of casting char to int */
9816         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9817         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9818         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9819       } else {
9820         emitpcodeNULLop(POC_CLRW);
9821
9822         if(offset)
9823           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9824         else
9825           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9826         
9827         emitpcode(POC_MOVLW,   popGetLit(0xff));
9828
9829         while (size--)
9830           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9831       }
9832     }
9833
9834 release:
9835     freeAsmop(right,NULL,ic,TRUE);
9836     freeAsmop(result,NULL,ic,TRUE);
9837
9838 }
9839
9840 /*-----------------------------------------------------------------*/
9841 /* genDjnz - generate decrement & jump if not zero instrucion      */
9842 /*-----------------------------------------------------------------*/
9843 static int genDjnz (iCode *ic, iCode *ifx)
9844 {
9845     symbol *lbl, *lbl1;
9846     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9847
9848     if (!ifx)
9849         return 0;
9850     
9851     /* if the if condition has a false label
9852        then we cannot save */
9853     if (IC_FALSE(ifx))
9854         return 0;
9855
9856     /* if the minus is not of the form 
9857        a = a - 1 */
9858     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9859         !IS_OP_LITERAL(IC_RIGHT(ic)))
9860         return 0;
9861
9862     if (operandLitValue(IC_RIGHT(ic)) != 1)
9863         return 0;
9864
9865     /* if the size of this greater than one then no
9866        saving */
9867     if (getSize(operandType(IC_RESULT(ic))) > 1)
9868         return 0;
9869
9870     /* otherwise we can save BIG */
9871     lbl = newiTempLabel(NULL);
9872     lbl1= newiTempLabel(NULL);
9873
9874     aopOp(IC_RESULT(ic),ic,FALSE);
9875     
9876     if (IS_AOP_PREG(IC_RESULT(ic))) {
9877         pic14_emitcode("dec","%s",
9878                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9879         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9880         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9881     } else {    
9882
9883
9884       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9885       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9886
9887       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9888       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9889
9890     }
9891 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9892 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9893 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9894 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9895
9896     
9897     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9898     ifx->generated = 1;
9899     return 1;
9900 }
9901
9902 /*-----------------------------------------------------------------*/
9903 /* genReceive - generate code for a receive iCode                  */
9904 /*-----------------------------------------------------------------*/
9905 static void genReceive (iCode *ic)
9906 {
9907   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9908
9909   if (isOperandInFarSpace(IC_RESULT(ic)) &&
9910       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9911         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9912
9913     int size = getSize(operandType(IC_RESULT(ic)));
9914     int offset =  fReturnSizePic - size;
9915     while (size--) {
9916       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9917                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9918       offset++;
9919     }
9920     aopOp(IC_RESULT(ic),ic,FALSE);
9921     size = AOP_SIZE(IC_RESULT(ic));
9922     offset = 0;
9923     while (size--) {
9924       pic14_emitcode ("pop","acc");
9925       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9926     }
9927
9928   } else {
9929     _G.accInUse++;
9930     aopOp(IC_RESULT(ic),ic,FALSE);
9931     _G.accInUse--;
9932     assignResultValue(IC_RESULT(ic));
9933   }
9934
9935   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9936 }
9937
9938 /*-----------------------------------------------------------------*/
9939 /* genDummyRead - generate code for dummy read of volatiles        */
9940 /*-----------------------------------------------------------------*/
9941 static void
9942 genDummyRead (iCode * ic)
9943 {
9944   pic14_emitcode ("; genDummyRead","");
9945   pic14_emitcode ("; not implemented","");
9946
9947   ic = ic;
9948 }
9949
9950 /*-----------------------------------------------------------------*/
9951 /* genpic14Code - generate code for pic14 based controllers        */
9952 /*-----------------------------------------------------------------*/
9953 /*
9954  * At this point, ralloc.c has gone through the iCode and attempted
9955  * to optimize in a way suitable for a PIC. Now we've got to generate
9956  * PIC instructions that correspond to the iCode.
9957  *
9958  * Once the instructions are generated, we'll pass through both the
9959  * peep hole optimizer and the pCode optimizer.
9960  *-----------------------------------------------------------------*/
9961
9962 void genpic14Code (iCode *lic)
9963 {
9964     iCode *ic;
9965     int cln = 0;
9966
9967     lineHead = lineCurr = NULL;
9968
9969     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9970     addpBlock(pb);
9971
9972     /* if debug information required */
9973     if (options.debug && currFunc) { 
9974       if (currFunc) {
9975         debugFile->writeFunction(currFunc);
9976         _G.debugLine = 1;
9977         if (IS_STATIC(currFunc->etype)) {
9978           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9979           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9980         } else {
9981           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9982           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9983         }
9984         _G.debugLine = 0;
9985       }
9986     }
9987
9988
9989     for (ic = lic ; ic ; ic = ic->next ) {
9990
9991       DEBUGpic14_emitcode(";ic","");
9992         if ( cln != ic->lineno ) {
9993             if ( options.debug ) {
9994                 _G.debugLine = 1;
9995                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9996                          FileBaseName(ic->filename),ic->lineno,
9997                          ic->level,ic->block);
9998                 _G.debugLine = 0;
9999             }
10000             /*
10001               pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
10002               pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
10003               printCLine(ic->filename, ic->lineno));
10004             */
10005             if (!options.noCcodeInAsm) {
10006               addpCode2pBlock(pb,
10007                               newpCodeCSource(ic->lineno, 
10008                                               ic->filename, 
10009                                               printCLine(ic->filename, ic->lineno)));
10010             }
10011
10012             cln = ic->lineno ;
10013         }
10014
10015         // if you want printILine too, look at ../mcs51/gen.c, i don't understand this :)
10016
10017         /* if the result is marked as
10018            spilt and rematerializable or code for
10019            this has already been generated then
10020            do nothing */
10021         if (resultRemat(ic) || ic->generated ) 
10022             continue ;
10023         
10024         /* depending on the operation */
10025         switch (ic->op) {
10026         case '!' :
10027             genNot(ic);
10028             break;
10029             
10030         case '~' :
10031             genCpl(ic);
10032             break;
10033             
10034         case UNARYMINUS:
10035             genUminus (ic);
10036             break;
10037             
10038         case IPUSH:
10039             genIpush (ic);
10040             break;
10041             
10042         case IPOP:
10043             /* IPOP happens only when trying to restore a 
10044                spilt live range, if there is an ifx statement
10045                following this pop then the if statement might
10046                be using some of the registers being popped which
10047                would destory the contents of the register so
10048                we need to check for this condition and handle it */
10049             if (ic->next            && 
10050                 ic->next->op == IFX &&
10051                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10052                 genIfx (ic->next,ic);
10053             else
10054                 genIpop (ic);
10055             break; 
10056             
10057         case CALL:
10058             genCall (ic);
10059             break;
10060             
10061         case PCALL:
10062             genPcall (ic);
10063             break;
10064             
10065         case FUNCTION:
10066             genFunction (ic);
10067             break;
10068             
10069         case ENDFUNCTION:
10070             genEndFunction (ic);
10071             break;
10072             
10073         case RETURN:
10074             genRet (ic);
10075             break;
10076             
10077         case LABEL:
10078             genLabel (ic);
10079             break;
10080             
10081         case GOTO:
10082             genGoto (ic);
10083             break;
10084             
10085         case '+' :
10086             genPlus (ic) ;
10087             break;
10088             
10089         case '-' :
10090             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10091                 genMinus (ic);
10092             break;
10093             
10094         case '*' :
10095             genMult (ic);
10096             break;
10097             
10098         case '/' :
10099             genDiv (ic) ;
10100             break;
10101             
10102         case '%' :
10103             genMod (ic);
10104             break;
10105             
10106         case '>' :
10107             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10108             break;
10109             
10110         case '<' :
10111             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10112             break;
10113             
10114         case LE_OP:
10115         case GE_OP:
10116         case NE_OP:
10117             
10118             /* note these two are xlated by algebraic equivalence
10119                during parsing SDCC.y */
10120             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10121                    "got '>=' or '<=' shouldn't have come here");
10122             break;      
10123             
10124         case EQ_OP:
10125             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10126             break;          
10127             
10128         case AND_OP:
10129             genAndOp (ic);
10130             break;
10131             
10132         case OR_OP:
10133             genOrOp (ic);
10134             break;
10135             
10136         case '^' :
10137             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10138             break;
10139             
10140         case '|' :
10141                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10142             break;
10143             
10144         case BITWISEAND:
10145             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10146             break;
10147             
10148         case INLINEASM:
10149             genInline (ic);
10150             break;
10151             
10152         case RRC:
10153             genRRC (ic);
10154             break;
10155             
10156         case RLC:
10157             genRLC (ic);
10158             break;
10159             
10160         case GETHBIT:
10161             genGetHbit (ic);
10162             break;
10163             
10164         case LEFT_OP:
10165             genLeftShift (ic);
10166             break;
10167             
10168         case RIGHT_OP:
10169             genRightShift (ic);
10170             break;
10171             
10172         case GET_VALUE_AT_ADDRESS:
10173             genPointerGet(ic);
10174             break;
10175             
10176         case '=' :
10177             if (POINTER_SET(ic))
10178                 genPointerSet(ic);
10179             else
10180                 genAssign(ic);
10181             break;
10182             
10183         case IFX:
10184             genIfx (ic,NULL);
10185             break;
10186             
10187         case ADDRESS_OF:
10188             genAddrOf (ic);
10189             break;
10190             
10191         case JUMPTABLE:
10192             genJumpTab (ic);
10193             break;
10194             
10195         case CAST:
10196             genCast (ic);
10197             break;
10198             
10199         case RECEIVE:
10200             genReceive(ic);
10201             break;
10202             
10203         case SEND:
10204             addSet(&_G.sendSet,ic);
10205             break;
10206
10207         case DUMMY_READ_VOLATILE:
10208           genDummyRead (ic);
10209           break;
10210
10211         default :
10212             ic = ic;
10213         }
10214     }
10215
10216
10217     /* now we are ready to call the
10218        peep hole optimizer */
10219     if (!options.nopeep) {
10220       peepHole (&lineHead);
10221     }
10222     /* now do the actual printing */
10223     printLine (lineHead,codeOutFile);
10224
10225 #ifdef PCODE_DEBUG
10226     DFPRINTF((stderr,"printing pBlock\n\n"));
10227     printpBlock(stdout,pb);
10228 #endif
10229
10230     return;
10231 }