Fixed bug #621531 (const & volatile confusion in the type chain).
[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 #if 0
614   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
615 #else
616   PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
617 #endif
618   PCOI(aop->aopu.pcop)->index = val;
619
620   DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
621                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
622                       val, IS_PTR_CONST(operandType(op)));
623
624   //    DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
625
626   allocDirReg (IC_LEFT(ic));
627
628   return aop;        
629 }
630
631 int aopIdx (asmop *aop, int offset)
632 {
633   if(!aop)
634     return -1;
635
636   if(aop->type !=  AOP_REG)
637     return -2;
638         
639   return aop->aopu.aop_reg[offset]->rIdx;
640
641 }
642 /*-----------------------------------------------------------------*/
643 /* regsInCommon - two operands have some registers in common       */
644 /*-----------------------------------------------------------------*/
645 static bool regsInCommon (operand *op1, operand *op2)
646 {
647     symbol *sym1, *sym2;
648     int i;
649
650     /* if they have registers in common */
651     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
652         return FALSE ;
653
654     sym1 = OP_SYMBOL(op1);
655     sym2 = OP_SYMBOL(op2);
656
657     if (sym1->nRegs == 0 || sym2->nRegs == 0)
658         return FALSE ;
659
660     for (i = 0 ; i < sym1->nRegs ; i++) {
661         int j;
662         if (!sym1->regs[i])
663             continue ;
664
665         for (j = 0 ; j < sym2->nRegs ;j++ ) {
666             if (!sym2->regs[j])
667                 continue ;
668
669             if (sym2->regs[j] == sym1->regs[i])
670                 return TRUE ;
671         }
672     }
673
674     return FALSE ;
675 }
676
677 /*-----------------------------------------------------------------*/
678 /* operandsEqu - equivalent                                        */
679 /*-----------------------------------------------------------------*/
680 static bool operandsEqu ( operand *op1, operand *op2)
681 {
682     symbol *sym1, *sym2;
683
684     /* if they not symbols */
685     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
686         return FALSE;
687
688     sym1 = OP_SYMBOL(op1);
689     sym2 = OP_SYMBOL(op2);
690
691     /* if both are itemps & one is spilt
692        and the other is not then false */
693     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
694         sym1->isspilt != sym2->isspilt )
695         return FALSE ;
696
697     /* if they are the same */
698     if (sym1 == sym2)
699         return TRUE ;
700
701     if (strcmp(sym1->rname,sym2->rname) == 0)
702         return TRUE;
703
704
705     /* if left is a tmp & right is not */
706     if (IS_ITEMP(op1)  && 
707         !IS_ITEMP(op2) &&
708         sym1->isspilt  &&
709         (sym1->usl.spillLoc == sym2))
710         return TRUE;
711
712     if (IS_ITEMP(op2)  && 
713         !IS_ITEMP(op1) &&
714         sym2->isspilt  &&
715         sym1->level > 0 &&
716         (sym2->usl.spillLoc == sym1))
717         return TRUE ;
718
719     return FALSE ;
720 }
721
722 /*-----------------------------------------------------------------*/
723 /* pic14_sameRegs - two asmops have the same registers                   */
724 /*-----------------------------------------------------------------*/
725 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
726 {
727     int i;
728
729     if (aop1 == aop2)
730         return TRUE ;
731
732     if (aop1->type != AOP_REG ||
733         aop2->type != AOP_REG )
734         return FALSE ;
735
736     if (aop1->size != aop2->size )
737         return FALSE ;
738
739     for (i = 0 ; i < aop1->size ; i++ )
740         if (aop1->aopu.aop_reg[i] !=
741             aop2->aopu.aop_reg[i] )
742             return FALSE ;
743
744     return TRUE ;
745 }
746
747 /*-----------------------------------------------------------------*/
748 /* aopOp - allocates an asmop for an operand  :                    */
749 /*-----------------------------------------------------------------*/
750 void aopOp (operand *op, iCode *ic, bool result)
751 {
752     asmop *aop;
753     symbol *sym;
754     int i;
755
756     if (!op)
757         return ;
758
759     //    DEBUGpic14_emitcode(";","%d",__LINE__);
760     /* if this a literal */
761     if (IS_OP_LITERAL(op)) {
762         op->aop = aop = newAsmop(AOP_LIT);
763         aop->aopu.aop_lit = op->operand.valOperand;
764         aop->size = getSize(operandType(op));
765         return;
766     }
767
768     {
769       sym_link *type = operandType(op);
770 #if 0
771       if(IS_PTR_CONST(type))
772 #else
773       if(IS_CODEPTR(type))
774 #endif
775         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
776     }
777
778     /* if already has a asmop then continue */
779     if (op->aop)
780         return ;
781
782     /* if the underlying symbol has a aop */
783     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
784       DEBUGpic14_emitcode(";","%d",__LINE__);
785         op->aop = OP_SYMBOL(op)->aop;
786         return;
787     }
788
789     /* if this is a true symbol */
790     if (IS_TRUE_SYMOP(op)) {    
791       //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
792       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
793       return ;
794     }
795
796     /* this is a temporary : this has
797     only four choices :
798     a) register
799     b) spillocation
800     c) rematerialize 
801     d) conditional   
802     e) can be a return use only */
803
804     sym = OP_SYMBOL(op);
805
806
807     /* if the type is a conditional */
808     if (sym->regType == REG_CND) {
809         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
810         aop->size = 0;
811         return;
812     }
813
814     /* if it is spilt then two situations
815     a) is rematerialize 
816     b) has a spill location */
817     if (sym->isspilt || sym->nRegs == 0) {
818
819       DEBUGpic14_emitcode(";","%d",__LINE__);
820         /* rematerialize it NOW */
821         if (sym->remat) {
822
823             sym->aop = op->aop = aop =
824                                       aopForRemat (op);
825             aop->size = getSize(sym->type);
826             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
827             return;
828         }
829
830         if (sym->accuse) {
831             int i;
832             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
833             aop->size = getSize(sym->type);
834             for ( i = 0 ; i < 2 ; i++ )
835                 aop->aopu.aop_str[i] = accUse[i];
836             DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
837             return;  
838         }
839
840         if (sym->ruonly ) {
841           if(sym->isptr) {  // && sym->uptr 
842             aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
843             aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
844
845             //PCOI(aop->aopu.pcop)->_const = 0;
846             //PCOI(aop->aopu.pcop)->index = 0;
847             /*
848               DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
849               __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
850             */
851             //allocDirReg (IC_LEFT(ic));
852
853             aop->size = getSize(sym->type);
854             DEBUGpic14_emitcode(";","%d",__LINE__);
855             return;
856
857           } else {
858
859             unsigned i;
860
861             aop = op->aop = sym->aop = newAsmop(AOP_STR);
862             aop->size = getSize(sym->type);
863             for ( i = 0 ; i < fReturnSizePic ; i++ )
864               aop->aopu.aop_str[i] = fReturn[i];
865
866             DEBUGpic14_emitcode(";","%d",__LINE__);
867             return;
868           }
869         }
870
871         /* else spill location  */
872         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
873             /* force a new aop if sizes differ */
874             sym->usl.spillLoc->aop = NULL;
875         }
876         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
877                             __FUNCTION__,__LINE__,
878                             sym->usl.spillLoc->rname,
879                             sym->rname, sym->usl.spillLoc->offset);
880
881         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
882         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
883         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
884                                           getSize(sym->type), 
885                                           sym->usl.spillLoc->offset);
886         aop->size = getSize(sym->type);
887
888         return;
889     }
890
891     {
892       sym_link *type = operandType(op);
893 #if 0
894       if(IS_PTR_CONST(type)) 
895 #else
896       if(IS_CODEPTR(type)) 
897 #endif
898         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
899     }
900
901     /* must be in a register */
902     DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
903     sym->aop = op->aop = aop = newAsmop(AOP_REG);
904     aop->size = sym->nRegs;
905     for ( i = 0 ; i < sym->nRegs ;i++)
906         aop->aopu.aop_reg[i] = sym->regs[i];
907 }
908
909 /*-----------------------------------------------------------------*/
910 /* freeAsmop - free up the asmop given to an operand               */
911 /*----------------------------------------------------------------*/
912 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
913 {   
914     asmop *aop ;
915
916     if (!op)
917         aop = aaop;
918     else 
919         aop = op->aop;
920
921     if (!aop)
922         return ;
923
924     if (aop->freed)
925         goto dealloc; 
926
927     aop->freed = 1;
928
929     /* depending on the asmop type only three cases need work AOP_RO
930        , AOP_R1 && AOP_STK */
931 #if 0
932     switch (aop->type) {
933         case AOP_R0 :
934             if (_G.r0Pushed ) {
935                 if (pop) {
936                     pic14_emitcode ("pop","ar0");     
937                     _G.r0Pushed--;
938                 }
939             }
940             bitVectUnSetBit(ic->rUsed,R0_IDX);
941             break;
942
943         case AOP_R1 :
944             if (_G.r1Pushed ) {
945                 if (pop) {
946                     pic14_emitcode ("pop","ar1");
947                     _G.r1Pushed--;
948                 }
949             }
950             bitVectUnSetBit(ic->rUsed,R1_IDX);          
951             break;
952
953         case AOP_STK :
954         {
955             int sz = aop->size;    
956             int stk = aop->aopu.aop_stk + aop->size;
957             bitVectUnSetBit(ic->rUsed,R0_IDX);
958             bitVectUnSetBit(ic->rUsed,R1_IDX);          
959
960             getFreePtr(ic,&aop,FALSE);
961             
962             if (options.stack10bit)
963             {
964                 /* I'm not sure what to do here yet... */
965                 /* #STUB */
966                 fprintf(stderr, 
967                         "*** Warning: probably generating bad code for "
968                         "10 bit stack mode.\n");
969             }
970             
971             if (stk) {
972                 pic14_emitcode ("mov","a,_bp");
973                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
974                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
975             } else {
976                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
977             }
978
979             while (sz--) {
980                 pic14_emitcode("pop","acc");
981                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
982                 if (!sz) break;
983                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
984             }
985             op->aop = aop;
986             freeAsmop(op,NULL,ic,TRUE);
987             if (_G.r0Pushed) {
988                 pic14_emitcode("pop","ar0");
989                 _G.r0Pushed--;
990             }
991
992             if (_G.r1Pushed) {
993                 pic14_emitcode("pop","ar1");
994                 _G.r1Pushed--;
995             }       
996         }
997     }
998 #endif
999
1000 dealloc:
1001     /* all other cases just dealloc */
1002     if (op ) {
1003         op->aop = NULL;
1004         if (IS_SYMOP(op)) {
1005             OP_SYMBOL(op)->aop = NULL;    
1006             /* if the symbol has a spill */
1007             if (SPIL_LOC(op))
1008                 SPIL_LOC(op)->aop = NULL;
1009         }
1010     }
1011 }
1012
1013 /*-----------------------------------------------------------------*/
1014 /* aopGet - for fetching value of the aop                          */
1015 /*-----------------------------------------------------------------*/
1016 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1017 {
1018     char *s = buffer ;
1019     char *rs;
1020
1021     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1022     /* offset is greater than
1023     size then zero */
1024     if (offset > (aop->size - 1) &&
1025         aop->type != AOP_LIT)
1026         return zero;
1027
1028     /* depending on type */
1029     switch (aop->type) {
1030         
1031     case AOP_R0:
1032     case AOP_R1:
1033         DEBUGpic14_emitcode(";","%d",__LINE__);
1034         /* if we need to increment it */       
1035         while (offset > aop->coff) {        
1036             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1037             aop->coff++;
1038         }
1039         
1040         while (offset < aop->coff) {
1041             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1042             aop->coff--;
1043         }
1044         
1045         aop->coff = offset ;
1046         if (aop->paged) {
1047             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1048             return (dname ? "acc" : "a");
1049         }       
1050         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1051         rs = Safe_calloc(1,strlen(s)+1);
1052         strcpy(rs,s);   
1053         return rs;
1054         
1055     case AOP_DPTR:
1056     case AOP_DPTR2:
1057         DEBUGpic14_emitcode(";","%d",__LINE__);
1058     if (aop->type == AOP_DPTR2)
1059     {
1060         genSetDPTR(1);
1061     }
1062     
1063         while (offset > aop->coff) {
1064             pic14_emitcode ("inc","dptr");
1065             aop->coff++;
1066         }
1067         
1068         while (offset < aop->coff) {        
1069             pic14_emitcode("lcall","__decdptr");
1070             aop->coff--;
1071         }
1072         
1073         aop->coff = offset;
1074         if (aop->code) {
1075             pic14_emitcode("clr","a");
1076             pic14_emitcode("movc","a,@a+dptr");
1077         }
1078     else {
1079             pic14_emitcode("movx","a,@dptr");
1080     }
1081             
1082     if (aop->type == AOP_DPTR2)
1083     {
1084         genSetDPTR(0);
1085     }
1086             
1087     return (dname ? "acc" : "a");
1088         
1089         
1090     case AOP_IMMD:
1091         if (bit16) 
1092             sprintf (s,"%s",aop->aopu.aop_immd);
1093         else
1094             if (offset) 
1095                 sprintf(s,"(%s >> %d)",
1096                         aop->aopu.aop_immd,
1097                         offset*8);
1098             else
1099                 sprintf(s,"%s",
1100                         aop->aopu.aop_immd);
1101         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1102         rs = Safe_calloc(1,strlen(s)+1);
1103         strcpy(rs,s);   
1104         return rs;
1105         
1106     case AOP_DIR:
1107       if (offset) {
1108         sprintf(s,"(%s + %d)",
1109                 aop->aopu.aop_dir,
1110                 offset);
1111         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1112       } else
1113             sprintf(s,"%s",aop->aopu.aop_dir);
1114         rs = Safe_calloc(1,strlen(s)+1);
1115         strcpy(rs,s);   
1116         return rs;
1117         
1118     case AOP_REG:
1119       //if (dname) 
1120       //    return aop->aopu.aop_reg[offset]->dname;
1121       //else
1122             return aop->aopu.aop_reg[offset]->name;
1123         
1124     case AOP_CRY:
1125       //pic14_emitcode(";","%d",__LINE__);
1126       return aop->aopu.aop_dir;
1127         
1128     case AOP_ACC:
1129         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1130         return "AOP_accumulator_bug";
1131
1132     case AOP_LIT:
1133         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1134         rs = Safe_calloc(1,strlen(s)+1);
1135         strcpy(rs,s);   
1136         return rs;
1137         
1138     case AOP_STR:
1139         aop->coff = offset ;
1140         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1141             dname)
1142             return "acc";
1143         DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1144         
1145         return aop->aopu.aop_str[offset];
1146         
1147     case AOP_PCODE:
1148       {
1149         pCodeOp *pcop = aop->aopu.pcop;
1150         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1151         if(pcop->name) {
1152           DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1153           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1154           sprintf(s,"%s", pcop->name);
1155         } else
1156           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1157
1158       }
1159       rs = Safe_calloc(1,strlen(s)+1);
1160       strcpy(rs,s);   
1161       return rs;
1162
1163     }
1164
1165     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1166            "aopget got unsupported aop->type");
1167     exit(0);
1168 }
1169
1170
1171 /*-----------------------------------------------------------------*/
1172 /* popGetTempReg - create a new temporary pCodeOp                  */
1173 /*-----------------------------------------------------------------*/
1174 pCodeOp *popGetTempReg(void)
1175 {
1176
1177   pCodeOp *pcop;
1178
1179   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1180   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1181     PCOR(pcop)->r->wasUsed=1;
1182     PCOR(pcop)->r->isFree=0;
1183   }
1184
1185   return pcop;
1186 }
1187
1188 /*-----------------------------------------------------------------*/
1189 /* popGetTempReg - create a new temporary pCodeOp                  */
1190 /*-----------------------------------------------------------------*/
1191 void popReleaseTempReg(pCodeOp *pcop)
1192 {
1193
1194   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1195     PCOR(pcop)->r->isFree = 1;
1196
1197 }
1198 /*-----------------------------------------------------------------*/
1199 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1200 /*-----------------------------------------------------------------*/
1201 pCodeOp *popGetLabel(unsigned int key)
1202 {
1203
1204   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1205
1206   if(key>(unsigned int)max_key)
1207     max_key = key;
1208
1209   return newpCodeOpLabel(NULL,key+100+labelOffset);
1210 }
1211
1212 /*-------------------------------------------------------------------*/
1213 /* popGetLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1214 /*-------------------------------------------------------------------*/
1215 pCodeOp *popGetHighLabel(unsigned int key)
1216 {
1217   pCodeOp *pcop;
1218   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1219
1220   if(key>(unsigned int)max_key)
1221     max_key = key;
1222
1223   pcop = newpCodeOpLabel(NULL,key+100+labelOffset);
1224   PCOLAB(pcop)->offset = 1;
1225   return pcop;
1226 }
1227
1228 /*-----------------------------------------------------------------*/
1229 /* popCopyReg - copy a pcode operator                              */
1230 /*-----------------------------------------------------------------*/
1231 pCodeOp *popCopyReg(pCodeOpReg *pc)
1232 {
1233   pCodeOpReg *pcor;
1234
1235   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1236   pcor->pcop.type = pc->pcop.type;
1237   if(pc->pcop.name) {
1238     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1239       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1240   } else
1241     pcor->pcop.name = NULL;
1242
1243   pcor->r = pc->r;
1244   pcor->rIdx = pc->rIdx;
1245   pcor->r->wasUsed=1;
1246
1247   //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1248
1249   return PCOP(pcor);
1250 }
1251 /*-----------------------------------------------------------------*/
1252 /* popGet - asm operator to pcode operator conversion              */
1253 /*-----------------------------------------------------------------*/
1254 pCodeOp *popGetLit(unsigned int lit)
1255 {
1256
1257   return newpCodeOpLit(lit);
1258 }
1259
1260
1261 /*-----------------------------------------------------------------*/
1262 /* popGetImmd - asm operator to pcode immediate conversion         */
1263 /*-----------------------------------------------------------------*/
1264 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1265 {
1266
1267   return newpCodeOpImmd(name, offset,index, 0, is_func);
1268 }
1269
1270
1271 /*-----------------------------------------------------------------*/
1272 /* popGet - asm operator to pcode operator conversion              */
1273 /*-----------------------------------------------------------------*/
1274 pCodeOp *popGetWithString(char *str)
1275 {
1276   pCodeOp *pcop;
1277
1278
1279   if(!str) {
1280     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1281     exit (1);
1282   }
1283
1284   pcop = newpCodeOp(str,PO_STR);
1285
1286   return pcop;
1287 }
1288
1289 /*-----------------------------------------------------------------*/
1290 /* popRegFromString -                                              */
1291 /*-----------------------------------------------------------------*/
1292 pCodeOp *popRegFromString(char *str, int size, int offset)
1293 {
1294
1295   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1296   pcop->type = PO_DIR;
1297
1298   DEBUGpic14_emitcode(";","%d",__LINE__);
1299
1300   if(!str)
1301     str = "BAD_STRING";
1302
1303   pcop->name = Safe_calloc(1,strlen(str)+1);
1304   strcpy(pcop->name,str);
1305
1306   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1307
1308   PCOR(pcop)->r = dirregWithName(pcop->name);
1309   if(PCOR(pcop)->r == NULL) {
1310     //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1311     PCOR(pcop)->r = allocRegByName (pcop->name,size);
1312     DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1313   } else {
1314     DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1315   }
1316   PCOR(pcop)->instance = offset;
1317
1318   return pcop;
1319 }
1320
1321 pCodeOp *popRegFromIdx(int rIdx)
1322 {
1323   pCodeOp *pcop;
1324
1325   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1326                        __FUNCTION__,__LINE__,rIdx);
1327
1328   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1329
1330   PCOR(pcop)->rIdx = rIdx;
1331   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1332   PCOR(pcop)->r->isFree = 0;
1333   PCOR(pcop)->r->wasUsed = 1;
1334
1335   pcop->type = PCOR(pcop)->r->pc_type;
1336
1337
1338   return pcop;
1339 }
1340 /*-----------------------------------------------------------------*/
1341 /* popGet - asm operator to pcode operator conversion              */
1342 /*-----------------------------------------------------------------*/
1343 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1344 {
1345   //char *s = buffer ;
1346     //char *rs;
1347
1348     pCodeOp *pcop;
1349
1350     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1351     /* offset is greater than
1352     size then zero */
1353
1354     if (offset > (aop->size - 1) &&
1355         aop->type != AOP_LIT)
1356       return NULL;  //zero;
1357
1358     /* depending on type */
1359     switch (aop->type) {
1360         
1361     case AOP_R0:
1362     case AOP_R1:
1363     case AOP_DPTR:
1364     case AOP_DPTR2:
1365     case AOP_ACC:
1366         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1367         return NULL;
1368         
1369     case AOP_IMMD:
1370       DEBUGpic14_emitcode(";","%d",__LINE__);
1371       return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1372
1373     case AOP_DIR:
1374       return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1375 #if 0
1376         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1377         pcop->type = PO_DIR;
1378
1379         /*
1380         if (offset)
1381             sprintf(s,"(%s + %d)",
1382                     aop->aopu.aop_dir,
1383                     offset);
1384         else
1385             sprintf(s,"%s",aop->aopu.aop_dir);
1386         pcop->name = Safe_calloc(1,strlen(s)+1);
1387         strcpy(pcop->name,s);   
1388         */
1389         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1390         strcpy(pcop->name,aop->aopu.aop_dir);   
1391         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1392         if(PCOR(pcop)->r == NULL) {
1393           //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1394           PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1395           DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1396         } else {
1397           DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1398         }
1399         PCOR(pcop)->instance = offset;
1400
1401         return pcop;
1402 #endif
1403         
1404     case AOP_REG:
1405       {
1406         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1407
1408         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1409         PCOR(pcop)->rIdx = rIdx;
1410         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1411         PCOR(pcop)->r->wasUsed=1;
1412         PCOR(pcop)->r->isFree=0;
1413
1414         PCOR(pcop)->instance = offset;
1415         pcop->type = PCOR(pcop)->r->pc_type;
1416         //rs = aop->aopu.aop_reg[offset]->name;
1417         DEBUGpic14_emitcode(";","%d regiser idx = %d ",__LINE__,rIdx);
1418         return pcop;
1419       }
1420
1421     case AOP_CRY:
1422       pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1423       PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1424       //if(PCOR(pcop)->r == NULL)
1425       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1426       return pcop;
1427         
1428     case AOP_LIT:
1429       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1430
1431     case AOP_STR:
1432       DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1433       return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1434       /*
1435       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1436       PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1437       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1438       pcop->type = PCOR(pcop)->r->pc_type;
1439       pcop->name = PCOR(pcop)->r->name;
1440
1441       return pcop;
1442       */
1443
1444     case AOP_PCODE:
1445       DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s) %d %s",pCodeOpType(aop->aopu.pcop),
1446                           __LINE__, 
1447                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1448       pcop = pCodeOpCopy(aop->aopu.pcop);
1449       PCOI(pcop)->offset = offset;
1450       return pcop;
1451     }
1452
1453     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1454            "popGet got unsupported aop->type");
1455     exit(0);
1456 }
1457 /*-----------------------------------------------------------------*/
1458 /* aopPut - puts a string for a aop                                */
1459 /*-----------------------------------------------------------------*/
1460 void aopPut (asmop *aop, char *s, int offset)
1461 {
1462     char *d = buffer ;
1463     symbol *lbl ;
1464
1465     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1466
1467     if (aop->size && offset > ( aop->size - 1)) {
1468         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1469                "aopPut got offset > aop->size");
1470         exit(0);
1471     }
1472
1473     /* will assign value to value */
1474     /* depending on where it is ofcourse */
1475     switch (aop->type) {
1476     case AOP_DIR:
1477       if (offset) {
1478         sprintf(d,"(%s + %d)",
1479                 aop->aopu.aop_dir,offset);
1480         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1481
1482       } else
1483             sprintf(d,"%s",aop->aopu.aop_dir);
1484         
1485         if (strcmp(d,s)) {
1486           DEBUGpic14_emitcode(";","%d",__LINE__);
1487           if(strcmp(s,"W"))
1488             pic14_emitcode("movf","%s,w",s);
1489           pic14_emitcode("movwf","%s",d);
1490
1491           if(strcmp(s,"W")) {
1492             pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1493             if(offset >= aop->size) {
1494               emitpcode(POC_CLRF,popGet(aop,offset));
1495               break;
1496             } else
1497               emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1498           }
1499
1500           emitpcode(POC_MOVWF,popGet(aop,offset));
1501
1502
1503         }
1504         break;
1505         
1506     case AOP_REG:
1507       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1508         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1509           /*
1510             if (*s == '@'           ||
1511                 strcmp(s,"r0") == 0 ||
1512                 strcmp(s,"r1") == 0 ||
1513                 strcmp(s,"r2") == 0 ||
1514                 strcmp(s,"r3") == 0 ||
1515                 strcmp(s,"r4") == 0 ||
1516                 strcmp(s,"r5") == 0 ||
1517                 strcmp(s,"r6") == 0 || 
1518                 strcmp(s,"r7") == 0 )
1519                 pic14_emitcode("mov","%s,%s  ; %d",
1520                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1521             else
1522           */
1523
1524           if(strcmp(s,"W")==0 )
1525             pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1526
1527           pic14_emitcode("movwf","%s",
1528                    aop->aopu.aop_reg[offset]->name);
1529
1530           if(strcmp(s,zero)==0) {
1531             emitpcode(POC_CLRF,popGet(aop,offset));
1532
1533           } else if(strcmp(s,"W")==0) {
1534             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1535             pcop->type = PO_GPR_REGISTER;
1536
1537             PCOR(pcop)->rIdx = -1;
1538             PCOR(pcop)->r = NULL;
1539
1540             DEBUGpic14_emitcode(";","%d",__LINE__);
1541             pcop->name = Safe_strdup(s);
1542             emitpcode(POC_MOVFW,pcop);
1543             emitpcode(POC_MOVWF,popGet(aop,offset));
1544           } else if(strcmp(s,one)==0) {
1545             emitpcode(POC_CLRF,popGet(aop,offset));
1546             emitpcode(POC_INCF,popGet(aop,offset));
1547           } else {
1548             emitpcode(POC_MOVWF,popGet(aop,offset));
1549           }
1550         }
1551         break;
1552         
1553     case AOP_DPTR:
1554     case AOP_DPTR2:
1555     
1556     if (aop->type == AOP_DPTR2)
1557     {
1558         genSetDPTR(1);
1559     }
1560     
1561         if (aop->code) {
1562             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1563                    "aopPut writting to code space");
1564             exit(0);
1565         }
1566         
1567         while (offset > aop->coff) {
1568             aop->coff++;
1569             pic14_emitcode ("inc","dptr");
1570         }
1571         
1572         while (offset < aop->coff) {
1573             aop->coff-- ;
1574             pic14_emitcode("lcall","__decdptr");
1575         }
1576         
1577         aop->coff = offset;
1578         
1579         /* if not in accumulater */
1580         MOVA(s);        
1581         
1582         pic14_emitcode ("movx","@dptr,a");
1583         
1584     if (aop->type == AOP_DPTR2)
1585     {
1586         genSetDPTR(0);
1587     }
1588         break;
1589         
1590     case AOP_R0:
1591     case AOP_R1:
1592         while (offset > aop->coff) {
1593             aop->coff++;
1594             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1595         }
1596         while (offset < aop->coff) {
1597             aop->coff-- ;
1598             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1599         }
1600         aop->coff = offset;
1601         
1602         if (aop->paged) {
1603             MOVA(s);           
1604             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1605             
1606         } else
1607             if (*s == '@') {
1608                 MOVA(s);
1609                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1610             } else
1611                 if (strcmp(s,"r0") == 0 ||
1612                     strcmp(s,"r1") == 0 ||
1613                     strcmp(s,"r2") == 0 ||
1614                     strcmp(s,"r3") == 0 ||
1615                     strcmp(s,"r4") == 0 ||
1616                     strcmp(s,"r5") == 0 ||
1617                     strcmp(s,"r6") == 0 || 
1618                     strcmp(s,"r7") == 0 ) {
1619                     char buffer[10];
1620                     sprintf(buffer,"a%s",s);
1621                     pic14_emitcode("mov","@%s,%s",
1622                              aop->aopu.aop_ptr->name,buffer);
1623                 } else
1624                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1625         
1626         break;
1627         
1628     case AOP_STK:
1629         if (strcmp(s,"a") == 0)
1630             pic14_emitcode("push","acc");
1631         else
1632             pic14_emitcode("push","%s",s);
1633         
1634         break;
1635         
1636     case AOP_CRY:
1637         /* if bit variable */
1638         if (!aop->aopu.aop_dir) {
1639             pic14_emitcode("clr","a");
1640             pic14_emitcode("rlc","a");
1641         } else {
1642             if (s == zero) 
1643                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1644             else
1645                 if (s == one)
1646                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1647                 else
1648                     if (!strcmp(s,"c"))
1649                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1650                     else {
1651                         lbl = newiTempLabel(NULL);
1652                         
1653                         if (strcmp(s,"a")) {
1654                             MOVA(s);
1655                         }
1656                         pic14_emitcode("clr","c");
1657                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1658                         pic14_emitcode("cpl","c");
1659                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1660                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1661                     }
1662         }
1663         break;
1664         
1665     case AOP_STR:
1666         aop->coff = offset;
1667         if (strcmp(aop->aopu.aop_str[offset],s))
1668             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1669         break;
1670         
1671     case AOP_ACC:
1672         aop->coff = offset;
1673         if (!offset && (strcmp(s,"acc") == 0))
1674             break;
1675         
1676         if (strcmp(aop->aopu.aop_str[offset],s))
1677             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1678         break;
1679
1680     default :
1681         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1682                "aopPut got unsupported aop->type");
1683         exit(0);    
1684     }    
1685
1686 }
1687
1688 /*-----------------------------------------------------------------*/
1689 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1690 /*-----------------------------------------------------------------*/
1691 void mov2w (asmop *aop, int offset)
1692 {
1693
1694   if(!aop)
1695     return;
1696
1697   DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1698
1699   if ( aop->type == AOP_PCODE ||
1700        aop->type == AOP_LIT ||
1701        aop->type == AOP_IMMD )
1702     emitpcode(POC_MOVLW,popGet(aop,offset));
1703   else
1704     emitpcode(POC_MOVFW,popGet(aop,offset));
1705
1706 }
1707
1708 /*-----------------------------------------------------------------*/
1709 /* reAdjustPreg - points a register back to where it should        */
1710 /*-----------------------------------------------------------------*/
1711 static void reAdjustPreg (asmop *aop)
1712 {
1713     int size ;
1714
1715     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1716     aop->coff = 0;
1717     if ((size = aop->size) <= 1)
1718         return ;
1719     size-- ;
1720     switch (aop->type) {
1721         case AOP_R0 :
1722         case AOP_R1 :
1723             while (size--)
1724                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1725             break;          
1726         case AOP_DPTR :
1727         case AOP_DPTR2:
1728             if (aop->type == AOP_DPTR2)
1729             {
1730                 genSetDPTR(1);
1731             } 
1732             while (size--)
1733             {
1734                 pic14_emitcode("lcall","__decdptr");
1735             }
1736                 
1737             if (aop->type == AOP_DPTR2)
1738             {
1739                 genSetDPTR(0);
1740             }                
1741             break;  
1742
1743     }   
1744
1745 }
1746
1747
1748 #if 0
1749 /*-----------------------------------------------------------------*/
1750 /* opIsGptr: returns non-zero if the passed operand is             */   
1751 /* a generic pointer type.                                         */
1752 /*-----------------------------------------------------------------*/ 
1753 static int opIsGptr(operand *op)
1754 {
1755     sym_link *type = operandType(op);
1756     
1757     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1758     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1759     {
1760         return 1;
1761     }
1762     return 0;        
1763 }
1764 #endif
1765
1766 /*-----------------------------------------------------------------*/
1767 /* pic14_getDataSize - get the operand data size                         */
1768 /*-----------------------------------------------------------------*/
1769 int pic14_getDataSize(operand *op)
1770 {
1771     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1772
1773
1774     return AOP_SIZE(op);
1775
1776     // tsd- in the pic port, the genptr size is 1, so this code here
1777     // fails. ( in the 8051 port, the size was 4).
1778 #if 0
1779     int size;
1780     size = AOP_SIZE(op);
1781     if (size == GPTRSIZE)
1782     {
1783         sym_link *type = operandType(op);
1784         if (IS_GENPTR(type))
1785         {
1786             /* generic pointer; arithmetic operations
1787              * should ignore the high byte (pointer type).
1788              */
1789             size--;
1790     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1791         }
1792     }
1793     return size;
1794 #endif
1795 }
1796
1797 /*-----------------------------------------------------------------*/
1798 /* pic14_outAcc - output Acc                                             */
1799 /*-----------------------------------------------------------------*/
1800 void pic14_outAcc(operand *result)
1801 {
1802   int size,offset;
1803   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1804   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1805
1806
1807   size = pic14_getDataSize(result);
1808   if(size){
1809     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1810     size--;
1811     offset = 1;
1812     /* unsigned or positive */
1813     while(size--)
1814       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1815   }
1816
1817 }
1818
1819 /*-----------------------------------------------------------------*/
1820 /* pic14_outBitC - output a bit C                                        */
1821 /*-----------------------------------------------------------------*/
1822 void pic14_outBitC(operand *result)
1823 {
1824
1825     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1826     /* if the result is bit */
1827     if (AOP_TYPE(result) == AOP_CRY) 
1828         aopPut(AOP(result),"c",0);
1829     else {
1830         pic14_emitcode("clr","a  ; %d", __LINE__);
1831         pic14_emitcode("rlc","a");
1832         pic14_outAcc(result);
1833     }
1834 }
1835
1836 /*-----------------------------------------------------------------*/
1837 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1838 /*-----------------------------------------------------------------*/
1839 void pic14_toBoolean(operand *oper)
1840 {
1841     int size = AOP_SIZE(oper) - 1;
1842     int offset = 1;
1843
1844     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1845
1846     if ( AOP_TYPE(oper) != AOP_ACC) {
1847       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1848     }
1849     while (size--) {
1850       emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1851     }
1852 }
1853
1854
1855 /*-----------------------------------------------------------------*/
1856 /* genNot - generate code for ! operation                          */
1857 /*-----------------------------------------------------------------*/
1858 static void genNot (iCode *ic)
1859 {
1860   symbol *tlbl;
1861   int size;
1862
1863   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1864   /* assign asmOps to operand & result */
1865   aopOp (IC_LEFT(ic),ic,FALSE);
1866   aopOp (IC_RESULT(ic),ic,TRUE);
1867
1868   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1869   /* if in bit space then a special case */
1870   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1871     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1872       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1873       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1874     } else {
1875       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1876       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1877       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1878     }
1879     goto release;
1880   }
1881
1882   size = AOP_SIZE(IC_LEFT(ic));
1883   if(size == 1) {
1884     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1885     emitpcode(POC_ANDLW,popGetLit(1));
1886     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1887     goto release;
1888   }
1889   pic14_toBoolean(IC_LEFT(ic));
1890
1891   tlbl = newiTempLabel(NULL);
1892   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1893   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1894   pic14_outBitC(IC_RESULT(ic));
1895
1896  release:    
1897   /* release the aops */
1898   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1899   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1900 }
1901
1902
1903 /*-----------------------------------------------------------------*/
1904 /* genCpl - generate code for complement                           */
1905 /*-----------------------------------------------------------------*/
1906 static void genCpl (iCode *ic)
1907 {
1908   operand *left, *result;
1909   int size, offset=0;  
1910
1911
1912   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1913   aopOp((left = IC_LEFT(ic)),ic,FALSE);
1914   aopOp((result=IC_RESULT(ic)),ic,TRUE);
1915
1916   /* if both are in bit space then 
1917      a special case */
1918   if (AOP_TYPE(result) == AOP_CRY &&
1919       AOP_TYPE(left) == AOP_CRY ) { 
1920
1921     pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1922     pic14_emitcode("cpl","c"); 
1923     pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1924     goto release; 
1925   } 
1926
1927   size = AOP_SIZE(result);
1928   while (size--) {
1929
1930     if(AOP_TYPE(left) == AOP_ACC) 
1931       emitpcode(POC_XORLW, popGetLit(0xff));
1932     else
1933       emitpcode(POC_COMFW,popGet(AOP(left),offset));
1934
1935     emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1936
1937   }
1938
1939
1940 release:
1941     /* release the aops */
1942     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1943     freeAsmop(result,NULL,ic,TRUE);
1944 }
1945
1946 /*-----------------------------------------------------------------*/
1947 /* genUminusFloat - unary minus for floating points                */
1948 /*-----------------------------------------------------------------*/
1949 static void genUminusFloat(operand *op,operand *result)
1950 {
1951     int size ,offset =0 ;
1952     char *l;
1953
1954     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1955     /* for this we just need to flip the 
1956     first it then copy the rest in place */
1957     size = AOP_SIZE(op) - 1;
1958     l = aopGet(AOP(op),3,FALSE,FALSE);
1959
1960     MOVA(l);    
1961
1962     pic14_emitcode("cpl","acc.7");
1963     aopPut(AOP(result),"a",3);    
1964
1965     while(size--) {
1966         aopPut(AOP(result),
1967                aopGet(AOP(op),offset,FALSE,FALSE),
1968                offset);
1969         offset++;
1970     }          
1971 }
1972
1973 /*-----------------------------------------------------------------*/
1974 /* genUminus - unary minus code generation                         */
1975 /*-----------------------------------------------------------------*/
1976 static void genUminus (iCode *ic)
1977 {
1978   int size, i;
1979   sym_link *optype, *rtype;
1980
1981
1982   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1983   /* assign asmops */
1984   aopOp(IC_LEFT(ic),ic,FALSE);
1985   aopOp(IC_RESULT(ic),ic,TRUE);
1986
1987   /* if both in bit space then special
1988      case */
1989   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1990       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1991
1992     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1993     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1994     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1995
1996     goto release; 
1997   } 
1998
1999   optype = operandType(IC_LEFT(ic));
2000   rtype = operandType(IC_RESULT(ic));
2001
2002   /* if float then do float stuff */
2003   if (IS_FLOAT(optype)) {
2004     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2005     goto release;
2006   }
2007
2008   /* otherwise subtract from zero by taking the 2's complement */
2009   size = AOP_SIZE(IC_LEFT(ic));
2010
2011   for(i=0; i<size; i++) {
2012     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2013       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2014     else {
2015       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2016       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2017     }
2018   }
2019
2020   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2021   for(i=1; i<size; i++) {
2022     emitSKPNZ;
2023     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2024   }
2025
2026  release:
2027   /* release the aops */
2028   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2029   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2030 }
2031
2032 /*-----------------------------------------------------------------*/
2033 /* saveRegisters - will look for a call and save the registers     */
2034 /*-----------------------------------------------------------------*/
2035 static void saveRegisters(iCode *lic) 
2036 {
2037     int i;
2038     iCode *ic;
2039     bitVect *rsave;
2040     sym_link *dtype;
2041
2042     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2043     /* look for call */
2044     for (ic = lic ; ic ; ic = ic->next) 
2045         if (ic->op == CALL || ic->op == PCALL)
2046             break;
2047
2048     if (!ic) {
2049         fprintf(stderr,"found parameter push with no function call\n");
2050         return ;
2051     }
2052
2053     /* if the registers have been saved already then
2054     do nothing */
2055     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2056         return ;
2057
2058     /* find the registers in use at this time 
2059     and push them away to safety */
2060     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2061                           ic->rUsed);
2062
2063     ic->regsSaved = 1;
2064     if (options.useXstack) {
2065         if (bitVectBitValue(rsave,R0_IDX))
2066             pic14_emitcode("mov","b,r0");
2067         pic14_emitcode("mov","r0,%s",spname);
2068         for (i = 0 ; i < pic14_nRegs ; i++) {
2069             if (bitVectBitValue(rsave,i)) {
2070                 if (i == R0_IDX)
2071                     pic14_emitcode("mov","a,b");
2072                 else
2073                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2074                 pic14_emitcode("movx","@r0,a");
2075                 pic14_emitcode("inc","r0");
2076             }
2077         }
2078         pic14_emitcode("mov","%s,r0",spname);
2079         if (bitVectBitValue(rsave,R0_IDX))
2080             pic14_emitcode("mov","r0,b");           
2081     }// else
2082     //for (i = 0 ; i < pic14_nRegs ; i++) {
2083     //    if (bitVectBitValue(rsave,i))
2084     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2085     //}
2086
2087     dtype = operandType(IC_LEFT(ic));
2088     if (currFunc && dtype && 
2089         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2090         IFFUNC_ISISR(currFunc->type) &&
2091         !ic->bankSaved) 
2092
2093         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2094
2095 }
2096 /*-----------------------------------------------------------------*/
2097 /* unsaveRegisters - pop the pushed registers                      */
2098 /*-----------------------------------------------------------------*/
2099 static void unsaveRegisters (iCode *ic)
2100 {
2101     int i;
2102     bitVect *rsave;
2103
2104     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2105     /* find the registers in use at this time 
2106     and push them away to safety */
2107     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2108                           ic->rUsed);
2109     
2110     if (options.useXstack) {
2111         pic14_emitcode("mov","r0,%s",spname);   
2112         for (i =  pic14_nRegs ; i >= 0 ; i--) {
2113             if (bitVectBitValue(rsave,i)) {
2114                 pic14_emitcode("dec","r0");
2115                 pic14_emitcode("movx","a,@r0");
2116                 if (i == R0_IDX)
2117                     pic14_emitcode("mov","b,a");
2118                 else
2119                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2120             }       
2121
2122         }
2123         pic14_emitcode("mov","%s,r0",spname);
2124         if (bitVectBitValue(rsave,R0_IDX))
2125             pic14_emitcode("mov","r0,b");
2126     } //else
2127     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2128     //    if (bitVectBitValue(rsave,i))
2129     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2130     //}
2131
2132 }  
2133
2134
2135 /*-----------------------------------------------------------------*/
2136 /* pushSide -                                                      */
2137 /*-----------------------------------------------------------------*/
2138 static void pushSide(operand * oper, int size)
2139 {
2140 #if 0
2141         int offset = 0;
2142     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2143         while (size--) {
2144                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2145                 if (AOP_TYPE(oper) != AOP_REG &&
2146                     AOP_TYPE(oper) != AOP_DIR &&
2147                     strcmp(l,"a") ) {
2148                         pic14_emitcode("mov","a,%s",l);
2149                         pic14_emitcode("push","acc");
2150                 } else
2151                         pic14_emitcode("push","%s",l);
2152         }
2153 #endif
2154 }
2155
2156 /*-----------------------------------------------------------------*/
2157 /* assignResultValue -                                             */
2158 /*-----------------------------------------------------------------*/
2159 static void assignResultValue(operand * oper)
2160 {
2161   int size = AOP_SIZE(oper);
2162
2163   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2164
2165   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2166
2167   if(!GpsuedoStkPtr) {
2168     /* The last byte in the assignment is in W */
2169     size--;
2170     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2171     GpsuedoStkPtr++;
2172   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2173   }
2174
2175   while (size--) {
2176     emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
2177     GpsuedoStkPtr++;
2178     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2179   }
2180 }
2181
2182
2183 /*-----------------------------------------------------------------*/
2184 /* genIpush - genrate code for pushing this gets a little complex  */
2185 /*-----------------------------------------------------------------*/
2186 static void genIpush (iCode *ic)
2187 {
2188
2189   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2190 #if 0
2191     int size, offset = 0 ;
2192     char *l;
2193
2194
2195     /* if this is not a parm push : ie. it is spill push 
2196     and spill push is always done on the local stack */
2197     if (!ic->parmPush) {
2198
2199         /* and the item is spilt then do nothing */
2200         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2201             return ;
2202
2203         aopOp(IC_LEFT(ic),ic,FALSE);
2204         size = AOP_SIZE(IC_LEFT(ic));
2205         /* push it on the stack */
2206         while(size--) {
2207             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2208             if (*l == '#') {
2209                 MOVA(l);
2210                 l = "acc";
2211             }
2212             pic14_emitcode("push","%s",l);
2213         }
2214         return ;        
2215     }
2216
2217     /* this is a paramter push: in this case we call
2218     the routine to find the call and save those
2219     registers that need to be saved */   
2220     saveRegisters(ic);
2221
2222     /* then do the push */
2223     aopOp(IC_LEFT(ic),ic,FALSE);
2224
2225
2226         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2227     size = AOP_SIZE(IC_LEFT(ic));
2228
2229     while (size--) {
2230         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2231         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2232             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2233             strcmp(l,"a") ) {
2234             pic14_emitcode("mov","a,%s",l);
2235             pic14_emitcode("push","acc");
2236         } else
2237             pic14_emitcode("push","%s",l);
2238     }       
2239
2240     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2241 #endif
2242 }
2243
2244 /*-----------------------------------------------------------------*/
2245 /* genIpop - recover the registers: can happen only for spilling   */
2246 /*-----------------------------------------------------------------*/
2247 static void genIpop (iCode *ic)
2248 {
2249   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2250 #if 0
2251     int size,offset ;
2252
2253
2254     /* if the temp was not pushed then */
2255     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2256         return ;
2257
2258     aopOp(IC_LEFT(ic),ic,FALSE);
2259     size = AOP_SIZE(IC_LEFT(ic));
2260     offset = (size-1);
2261     while (size--) 
2262         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2263                                    FALSE,TRUE));
2264
2265     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2266 #endif
2267 }
2268
2269 /*-----------------------------------------------------------------*/
2270 /* unsaverbank - restores the resgister bank from stack            */
2271 /*-----------------------------------------------------------------*/
2272 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2273 {
2274   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2275 #if 0
2276     int i;
2277     asmop *aop ;
2278     regs *r = NULL;
2279
2280     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2281     if (popPsw) {
2282         if (options.useXstack) {
2283             aop = newAsmop(0);
2284             r = getFreePtr(ic,&aop,FALSE);
2285             
2286             
2287             pic14_emitcode("mov","%s,_spx",r->name);
2288             pic14_emitcode("movx","a,@%s",r->name);
2289             pic14_emitcode("mov","psw,a");
2290             pic14_emitcode("dec","%s",r->name);
2291             
2292         }else
2293             pic14_emitcode ("pop","psw");
2294     }
2295
2296     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2297         if (options.useXstack) {       
2298             pic14_emitcode("movx","a,@%s",r->name);
2299             //pic14_emitcode("mov","(%s+%d),a",
2300             //       regspic14[i].base,8*bank+regspic14[i].offset);
2301             pic14_emitcode("dec","%s",r->name);
2302
2303         } else 
2304           pic14_emitcode("pop",""); //"(%s+%d)",
2305         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2306     }
2307
2308     if (options.useXstack) {
2309
2310         pic14_emitcode("mov","_spx,%s",r->name);
2311         freeAsmop(NULL,aop,ic,TRUE);
2312
2313     }
2314 #endif 
2315 }
2316
2317 /*-----------------------------------------------------------------*/
2318 /* saverbank - saves an entire register bank on the stack          */
2319 /*-----------------------------------------------------------------*/
2320 static void saverbank (int bank, iCode *ic, bool pushPsw)
2321 {
2322   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2323 #if 0
2324     int i;
2325     asmop *aop ;
2326     regs *r = NULL;
2327
2328     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2329     if (options.useXstack) {
2330
2331         aop = newAsmop(0);
2332         r = getFreePtr(ic,&aop,FALSE);  
2333         pic14_emitcode("mov","%s,_spx",r->name);
2334
2335     }
2336
2337     for (i = 0 ; i < pic14_nRegs ;i++) {
2338         if (options.useXstack) {
2339             pic14_emitcode("inc","%s",r->name);
2340             //pic14_emitcode("mov","a,(%s+%d)",
2341             //         regspic14[i].base,8*bank+regspic14[i].offset);
2342             pic14_emitcode("movx","@%s,a",r->name);           
2343         } else 
2344           pic14_emitcode("push","");// "(%s+%d)",
2345                      //regspic14[i].base,8*bank+regspic14[i].offset);
2346     }
2347     
2348     if (pushPsw) {
2349         if (options.useXstack) {
2350             pic14_emitcode("mov","a,psw");
2351             pic14_emitcode("movx","@%s,a",r->name);     
2352             pic14_emitcode("inc","%s",r->name);
2353             pic14_emitcode("mov","_spx,%s",r->name);       
2354             freeAsmop (NULL,aop,ic,TRUE);
2355             
2356         } else
2357             pic14_emitcode("push","psw");
2358         
2359         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2360     }
2361     ic->bankSaved = 1;
2362 #endif
2363 }
2364
2365 /*-----------------------------------------------------------------*/
2366 /* genCall - generates a call statement                            */
2367 /*-----------------------------------------------------------------*/
2368 static void genCall (iCode *ic)
2369 {
2370   sym_link *dtype;   
2371
2372   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2373
2374   /* if caller saves & we have not saved then */
2375   if (!ic->regsSaved)
2376     saveRegisters(ic);
2377
2378   /* if we are calling a function that is not using
2379      the same register bank then we need to save the
2380      destination registers on the stack */
2381   dtype = operandType(IC_LEFT(ic));
2382   if (currFunc && dtype && 
2383       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2384       IFFUNC_ISISR(currFunc->type) &&
2385       !ic->bankSaved) 
2386
2387     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2388
2389   /* if send set is not empty the assign */
2390   if (_G.sendSet) {
2391     iCode *sic;
2392     /* For the Pic port, there is no data stack.
2393      * So parameters passed to functions are stored
2394      * in registers. (The pCode optimizer will get
2395      * rid of most of these :).
2396      */
2397     int psuedoStkPtr=-1; 
2398     int firstTimeThruLoop = 1;
2399
2400     _G.sendSet = reverseSet(_G.sendSet);
2401
2402     /* First figure how many parameters are getting passed */
2403     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2404          sic = setNextItem(_G.sendSet)) {
2405
2406       aopOp(IC_LEFT(sic),sic,FALSE);
2407       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2408       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2409     }
2410
2411     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2412          sic = setNextItem(_G.sendSet)) {
2413       int size, offset = 0;
2414
2415       aopOp(IC_LEFT(sic),sic,FALSE);
2416       size = AOP_SIZE(IC_LEFT(sic));
2417
2418       while (size--) {
2419         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2420                              AopType(AOP_TYPE(IC_LEFT(sic))));
2421
2422         if(!firstTimeThruLoop) {
2423           /* If this is not the first time we've been through the loop
2424            * then we need to save the parameter in a temporary
2425            * register. The last byte of the last parameter is
2426            * passed in W. */
2427           emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr));
2428
2429         }
2430         firstTimeThruLoop=0;
2431
2432         //if (strcmp(l,fReturn[offset])) {
2433         mov2w (AOP(IC_LEFT(sic)),  offset);
2434 /*
2435         if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
2436              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2437           emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset));
2438         else
2439           emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset));
2440 */
2441         //}
2442         offset++;
2443       }
2444       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2445     }
2446     _G.sendSet = NULL;
2447   }
2448   /* make the call */
2449   emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2450                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2451                                       OP_SYMBOL(IC_LEFT(ic))->name));
2452
2453   GpsuedoStkPtr=0;
2454   /* if we need assign a result value */
2455   if ((IS_ITEMP(IC_RESULT(ic)) && 
2456        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2457         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2458       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2459
2460     _G.accInUse++;
2461     aopOp(IC_RESULT(ic),ic,FALSE);
2462     _G.accInUse--;
2463
2464     assignResultValue(IC_RESULT(ic));
2465
2466     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2467                          AopType(AOP_TYPE(IC_RESULT(ic))));
2468                 
2469     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2470   }
2471
2472   /* adjust the stack for parameters if 
2473      required */
2474   if (ic->parmBytes) {
2475     int i;
2476     if (ic->parmBytes > 3) {
2477       pic14_emitcode("mov","a,%s",spname);
2478       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2479       pic14_emitcode("mov","%s,a",spname);
2480     } else 
2481       for ( i = 0 ; i <  ic->parmBytes ;i++)
2482         pic14_emitcode("dec","%s",spname);
2483
2484   }
2485
2486   /* if register bank was saved then pop them */
2487   if (ic->bankSaved)
2488     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2489
2490   /* if we hade saved some registers then unsave them */
2491   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2492     unsaveRegisters (ic);
2493
2494
2495 }
2496
2497 /*-----------------------------------------------------------------*/
2498 /* genPcall - generates a call by pointer statement                */
2499 /*-----------------------------------------------------------------*/
2500 static void genPcall (iCode *ic)
2501 {
2502     sym_link *dtype;
2503     symbol *albl = newiTempLabel(NULL);
2504     symbol *blbl = newiTempLabel(NULL);
2505     PIC_OPCODE poc;
2506     operand *left;
2507
2508     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2509     /* if caller saves & we have not saved then */
2510     if (!ic->regsSaved)
2511         saveRegisters(ic);
2512
2513     /* if we are calling a function that is not using
2514     the same register bank then we need to save the
2515     destination registers on the stack */
2516     dtype = operandType(IC_LEFT(ic));
2517     if (currFunc && dtype && 
2518         IFFUNC_ISISR(currFunc->type) &&
2519         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2520         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2521
2522     left = IC_LEFT(ic);
2523     aopOp(left,ic,FALSE);
2524     DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2525
2526     pushSide(IC_LEFT(ic), FPTRSIZE);
2527
2528     /* if send set is not empty, assign parameters */
2529     if (_G.sendSet) {
2530
2531         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2532         /* no way to pass args - W always gets used to make the call */
2533     }
2534 /* first idea - factor out a common helper function and call it.
2535    But don't know how to get it generated only once in its own block
2536
2537     if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2538             char *rname;
2539             char *buffer;
2540             rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2541             DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2542             buffer = Safe_calloc(1,strlen(rname)+16);
2543             sprintf(buffer, "%s_goto_helper", rname);
2544             addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2545             free(buffer);
2546     }
2547 */
2548     emitpcode(POC_CALL,popGetLabel(albl->key));
2549     emitpcodePagesel(popGetLabel(blbl->key)->name); /* Must restore PCLATH before goto, without destroying W */
2550     emitpcode(POC_GOTO,popGetLabel(blbl->key));
2551     emitpLabel(albl->key);
2552
2553     poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
2554     
2555     emitpcode(poc,popGet(AOP(left),1));
2556     emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2557     emitpcode(poc,popGet(AOP(left),0));
2558     emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2559
2560     emitpLabel(blbl->key);
2561
2562     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2563
2564     /* if we need to assign a result value */
2565     if ((IS_ITEMP(IC_RESULT(ic)) &&
2566          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2567           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2568         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2569
2570         _G.accInUse++;
2571         aopOp(IC_RESULT(ic),ic,FALSE);
2572         _G.accInUse--;
2573         
2574         assignResultValue(IC_RESULT(ic));
2575
2576         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2577     }
2578
2579     /* if register bank was saved then unsave them */
2580     if (currFunc && dtype && 
2581         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2582         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2583
2584     /* if we hade saved some registers then
2585     unsave them */
2586     if (ic->regsSaved)
2587         unsaveRegisters (ic);
2588
2589 }
2590
2591 /*-----------------------------------------------------------------*/
2592 /* resultRemat - result  is rematerializable                       */
2593 /*-----------------------------------------------------------------*/
2594 static int resultRemat (iCode *ic)
2595 {
2596   //    DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2597   if (SKIP_IC(ic) || ic->op == IFX)
2598     return 0;
2599
2600   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2601     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2602     if (sym->remat && !POINTER_SET(ic)) 
2603       return 1;
2604   }
2605
2606   return 0;
2607 }
2608
2609 #if defined(__BORLANDC__) || defined(_MSC_VER)
2610 #define STRCASECMP stricmp
2611 #else
2612 #define STRCASECMP strcasecmp
2613 #endif
2614
2615 #if 0
2616 /*-----------------------------------------------------------------*/
2617 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2618 /*-----------------------------------------------------------------*/
2619 static bool inExcludeList(char *s)
2620 {
2621   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2622     int i =0;
2623     
2624     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2625     if (options.excludeRegs[i] &&
2626     STRCASECMP(options.excludeRegs[i],"none") == 0)
2627         return FALSE ;
2628
2629     for ( i = 0 ; options.excludeRegs[i]; i++) {
2630         if (options.excludeRegs[i] &&
2631         STRCASECMP(s,options.excludeRegs[i]) == 0)
2632             return TRUE;
2633     }
2634     return FALSE ;
2635 }
2636 #endif
2637
2638 /*-----------------------------------------------------------------*/
2639 /* genFunction - generated code for function entry                 */
2640 /*-----------------------------------------------------------------*/
2641 static void genFunction (iCode *ic)
2642 {
2643     symbol *sym;
2644     sym_link *ftype;
2645
2646     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2647
2648     labelOffset += (max_key+4);
2649     max_key=0;
2650     GpsuedoStkPtr=0;
2651     _G.nRegsSaved = 0;
2652     /* create the function header */
2653     pic14_emitcode(";","-----------------------------------------");
2654     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2655     pic14_emitcode(";","-----------------------------------------");
2656
2657     pic14_emitcode("","%s:",sym->rname);
2658     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2659
2660     ftype = operandType(IC_LEFT(ic));
2661
2662     /* if critical function then turn interrupts off */
2663     if (IFFUNC_ISCRITICAL(ftype))
2664         pic14_emitcode("clr","ea");
2665
2666     /* here we need to generate the equates for the
2667        register bank if required */
2668 #if 0
2669     if (FUNC_REGBANK(ftype) != rbank) {
2670         int i ;
2671
2672         rbank = FUNC_REGBANK(ftype);
2673         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2674             if (strcmp(regspic14[i].base,"0") == 0)
2675                 pic14_emitcode("","%s = 0x%02x",
2676                          regspic14[i].dname,
2677                          8*rbank+regspic14[i].offset);
2678             else
2679                 pic14_emitcode ("","%s = %s + 0x%02x",
2680                           regspic14[i].dname,
2681                           regspic14[i].base,
2682                           8*rbank+regspic14[i].offset);
2683         }
2684     }
2685 #endif
2686
2687     /* if this is an interrupt service routine */
2688     if (IFFUNC_ISISR(sym->type)) {
2689 /*  already done in pic14createInterruptVect() - delete me
2690       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2691       emitpcodeNULLop(POC_NOP);
2692       emitpcodeNULLop(POC_NOP);
2693       emitpcodeNULLop(POC_NOP);
2694 */
2695       emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2696       emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2697       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2698       emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2699       emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2700       emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2701       emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* durring an interrupt PCLATH must be cleared before a goto or call statement */
2702
2703       pBlockConvert2ISR(pb);
2704 #if 0  
2705         if (!inExcludeList("acc"))          
2706             pic14_emitcode ("push","acc");      
2707         if (!inExcludeList("b"))
2708             pic14_emitcode ("push","b");
2709         if (!inExcludeList("dpl"))
2710             pic14_emitcode ("push","dpl");
2711         if (!inExcludeList("dph"))
2712             pic14_emitcode ("push","dph");
2713         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2714         {
2715             pic14_emitcode ("push", "dpx");
2716             /* Make sure we're using standard DPTR */
2717             pic14_emitcode ("push", "dps");
2718             pic14_emitcode ("mov", "dps, #0x00");
2719             if (options.stack10bit)
2720             {   
2721                 /* This ISR could conceivably use DPTR2. Better save it. */
2722                 pic14_emitcode ("push", "dpl1");
2723                 pic14_emitcode ("push", "dph1");
2724                 pic14_emitcode ("push", "dpx1");
2725             }
2726         }
2727         /* if this isr has no bank i.e. is going to
2728            run with bank 0 , then we need to save more
2729            registers :-) */
2730         if (!FUNC_REGBANK(sym->type)) {
2731
2732             /* if this function does not call any other
2733                function then we can be economical and
2734                save only those registers that are used */
2735             if (! IFFUNC_HASFCALL(sym->type)) {
2736                 int i;
2737
2738                 /* if any registers used */
2739                 if (sym->regsUsed) {
2740                     /* save the registers used */
2741                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2742                         if (bitVectBitValue(sym->regsUsed,i) ||
2743                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2744                           pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);                         
2745                     }
2746                 }
2747                 
2748             } else {
2749                 /* this function has  a function call cannot
2750                    determines register usage so we will have the
2751                    entire bank */
2752                 saverbank(0,ic,FALSE);
2753             }       
2754         }
2755 #endif
2756     } else {
2757         /* if callee-save to be used for this function
2758            then save the registers being used in this function */
2759         if (IFFUNC_CALLEESAVES(sym->type)) {
2760             int i;
2761             
2762             /* if any registers used */
2763             if (sym->regsUsed) {
2764                 /* save the registers used */
2765                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2766                     if (bitVectBitValue(sym->regsUsed,i) ||
2767                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2768                       //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2769                         _G.nRegsSaved++;
2770                     }
2771                 }
2772             }
2773         }
2774     }
2775
2776     /* set the register bank to the desired value */
2777     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2778         pic14_emitcode("push","psw");
2779         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2780     }
2781
2782     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2783
2784         if (options.useXstack) {
2785             pic14_emitcode("mov","r0,%s",spname);
2786             pic14_emitcode("mov","a,_bp");
2787             pic14_emitcode("movx","@r0,a");
2788             pic14_emitcode("inc","%s",spname);
2789         }
2790         else
2791         {
2792             /* set up the stack */
2793             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2794         }
2795         pic14_emitcode ("mov","_bp,%s",spname);
2796     }
2797
2798     /* adjust the stack for the function */
2799     if (sym->stack) {
2800
2801         int i = sym->stack;
2802         if (i > 256 ) 
2803             werror(W_STACK_OVERFLOW,sym->name);
2804
2805         if (i > 3 && sym->recvSize < 4) {              
2806
2807             pic14_emitcode ("mov","a,sp");
2808             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2809             pic14_emitcode ("mov","sp,a");
2810            
2811         }
2812         else
2813             while(i--)
2814                 pic14_emitcode("inc","sp");
2815     }
2816
2817      if (sym->xstack) {
2818
2819         pic14_emitcode ("mov","a,_spx");
2820         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2821         pic14_emitcode ("mov","_spx,a");
2822     }    
2823
2824 }
2825
2826 /*-----------------------------------------------------------------*/
2827 /* genEndFunction - generates epilogue for functions               */
2828 /*-----------------------------------------------------------------*/
2829 static void genEndFunction (iCode *ic)
2830 {
2831     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2832
2833     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2834
2835     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2836     {
2837         pic14_emitcode ("mov","%s,_bp",spname);
2838     }
2839
2840     /* if use external stack but some variables were
2841     added to the local stack then decrement the
2842     local stack */
2843     if (options.useXstack && sym->stack) {      
2844         pic14_emitcode("mov","a,sp");
2845         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2846         pic14_emitcode("mov","sp,a");
2847     }
2848
2849
2850     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2851         if (options.useXstack) {
2852             pic14_emitcode("mov","r0,%s",spname);
2853             pic14_emitcode("movx","a,@r0");
2854             pic14_emitcode("mov","_bp,a");
2855             pic14_emitcode("dec","%s",spname);
2856         }
2857         else
2858         {
2859             pic14_emitcode ("pop","_bp");
2860         }
2861     }
2862
2863     /* restore the register bank  */    
2864     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2865         pic14_emitcode ("pop","psw");
2866
2867     if (IFFUNC_ISISR(sym->type)) {
2868
2869         /* now we need to restore the registers */
2870         /* if this isr has no bank i.e. is going to
2871            run with bank 0 , then we need to save more
2872            registers :-) */
2873         if (!FUNC_REGBANK(sym->type)) {
2874             
2875             /* if this function does not call any other
2876                function then we can be economical and
2877                save only those registers that are used */
2878             if (! IFFUNC_HASFCALL(sym->type)) {
2879                 int i;
2880                 
2881                 /* if any registers used */
2882                 if (sym->regsUsed) {
2883                     /* save the registers used */
2884                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2885                         if (bitVectBitValue(sym->regsUsed,i) ||
2886                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2887                           pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2888                     }
2889                 }
2890                 
2891             } else {
2892                 /* this function has  a function call cannot
2893                    determines register usage so we will have the
2894                    entire bank */
2895                 unsaverbank(0,ic,FALSE);
2896             }       
2897         }
2898 #if 0
2899         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2900         {
2901             if (options.stack10bit)
2902             {
2903                 pic14_emitcode ("pop", "dpx1");
2904                 pic14_emitcode ("pop", "dph1");
2905                 pic14_emitcode ("pop", "dpl1");
2906             }   
2907             pic14_emitcode ("pop", "dps");
2908             pic14_emitcode ("pop", "dpx");
2909         }
2910         if (!inExcludeList("dph"))
2911             pic14_emitcode ("pop","dph");
2912         if (!inExcludeList("dpl"))
2913             pic14_emitcode ("pop","dpl");
2914         if (!inExcludeList("b"))
2915             pic14_emitcode ("pop","b");
2916         if (!inExcludeList("acc"))
2917             pic14_emitcode ("pop","acc");
2918
2919         if (IFFUNC_ISCRITICAL(sym->type))
2920             pic14_emitcode("setb","ea");
2921 #endif
2922
2923         /* if debug then send end of function */
2924 /*      if (options.debug && currFunc) { */
2925         if (currFunc) {
2926             _G.debugLine = 1;
2927             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2928                      FileBaseName(ic->filename),currFunc->lastLine,
2929                      ic->level,ic->block); 
2930             if (IS_STATIC(currFunc->etype))         
2931                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2932             else
2933                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2934             _G.debugLine = 0;
2935         }
2936
2937         pic14_emitcode ("reti","");
2938         emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2939         emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2940         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2941         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2942         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2943         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2944         emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2945         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2946         emitpcodeNULLop(POC_RETFIE);
2947     }
2948     else {
2949         if (IFFUNC_ISCRITICAL(sym->type))
2950             pic14_emitcode("setb","ea");
2951         
2952         if (IFFUNC_CALLEESAVES(sym->type)) {
2953             int i;
2954             
2955             /* if any registers used */
2956             if (sym->regsUsed) {
2957                 /* save the registers used */
2958                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2959                     if (bitVectBitValue(sym->regsUsed,i) ||
2960                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2961                       pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2962                 }
2963             }
2964             
2965         }
2966
2967         /* if debug then send end of function */
2968         if (currFunc) {
2969             _G.debugLine = 1;
2970             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2971                      FileBaseName(ic->filename),currFunc->lastLine,
2972                      ic->level,ic->block); 
2973             if (IS_STATIC(currFunc->etype))         
2974                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2975             else
2976                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2977             _G.debugLine = 0;
2978         }
2979
2980         pic14_emitcode ("return","");
2981         emitpcodeNULLop(POC_RETURN);
2982
2983         /* Mark the end of a function */
2984         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2985     }
2986
2987 }
2988
2989 /*-----------------------------------------------------------------*/
2990 /* genRet - generate code for return statement                     */
2991 /*-----------------------------------------------------------------*/
2992 static void genRet (iCode *ic)
2993 {
2994   int size,offset = 0 , pushed = 0;
2995     
2996   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2997   /* if we have no return value then
2998      just generate the "ret" */
2999   if (!IC_LEFT(ic)) 
3000     goto jumpret;       
3001     
3002   /* we have something to return then
3003      move the return value into place */
3004   aopOp(IC_LEFT(ic),ic,FALSE);
3005   size = AOP_SIZE(IC_LEFT(ic));
3006     
3007   while (size--) {
3008     char *l ;
3009     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3010       /* #NOCHANGE */
3011       l = aopGet(AOP(IC_LEFT(ic)),offset++,
3012                  FALSE,TRUE);
3013       pic14_emitcode("push","%s",l);
3014       pushed++;
3015     } else {
3016       l = aopGet(AOP(IC_LEFT(ic)),offset,
3017                  FALSE,FALSE);
3018       if (strcmp(fReturn[offset],l)) {
3019       if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
3020            AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
3021           ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3022           ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3023           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
3024         }else {
3025           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3026         }
3027         if(size) {
3028           emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
3029         }
3030         offset++;
3031       }
3032     }
3033   }    
3034
3035   if (pushed) {
3036     while(pushed) {
3037       pushed--;
3038       if (strcmp(fReturn[pushed],"a"))
3039         pic14_emitcode("pop",fReturn[pushed]);
3040       else
3041         pic14_emitcode("pop","acc");
3042     }
3043   }
3044   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3045     
3046  jumpret:
3047   /* generate a jump to the return label
3048      if the next is not the return statement */
3049   if (!(ic->next && ic->next->op == LABEL &&
3050         IC_LABEL(ic->next) == returnLabel)) {
3051         
3052     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3053     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3054   }
3055     
3056 }
3057
3058 /*-----------------------------------------------------------------*/
3059 /* genLabel - generates a label                                    */
3060 /*-----------------------------------------------------------------*/
3061 static void genLabel (iCode *ic)
3062 {
3063     /* special case never generate */
3064     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3065     if (IC_LABEL(ic) == entryLabel)
3066         return ;
3067
3068     emitpLabel(IC_LABEL(ic)->key);
3069     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3070 }
3071
3072 /*-----------------------------------------------------------------*/
3073 /* genGoto - generates a goto                                      */
3074 /*-----------------------------------------------------------------*/
3075 //tsd
3076 static void genGoto (iCode *ic)
3077 {
3078   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3079   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3080 }
3081
3082
3083 /*-----------------------------------------------------------------*/
3084 /* genMultbits :- multiplication of bits                           */
3085 /*-----------------------------------------------------------------*/
3086 static void genMultbits (operand *left, 
3087                          operand *right, 
3088                          operand *result)
3089 {
3090   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3091
3092   if(!pic14_sameRegs(AOP(result),AOP(right)))
3093     emitpcode(POC_BSF,  popGet(AOP(result),0));
3094
3095   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3096   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3097   emitpcode(POC_BCF,  popGet(AOP(result),0));
3098
3099 }
3100
3101
3102 /*-----------------------------------------------------------------*/
3103 /* genMultOneByte : 8 bit multiplication & division                */
3104 /*-----------------------------------------------------------------*/
3105 static void genMultOneByte (operand *left,
3106                             operand *right,
3107                             operand *result)
3108 {
3109   sym_link *opetype = operandType(result);
3110
3111   // symbol *lbl ;
3112   int size,offset;
3113
3114   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3115   DEBUGpic14_AopType(__LINE__,left,right,result);
3116   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3117
3118   /* (if two literals, the value is computed before) */
3119   /* if one literal, literal on the right */
3120   if (AOP_TYPE(left) == AOP_LIT){
3121     operand *t = right;
3122     right = left;
3123     left = t;
3124   }
3125
3126   size = AOP_SIZE(result);
3127   if(size == 1) {
3128
3129     if (AOP_TYPE(right) == AOP_LIT){
3130       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3131                      aopGet(AOP(right),0,FALSE,FALSE), 
3132                      aopGet(AOP(left),0,FALSE,FALSE), 
3133                      aopGet(AOP(result),0,FALSE,FALSE));
3134       pic14_emitcode("call","genMultLit");
3135     } else {
3136       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3137                      aopGet(AOP(right),0,FALSE,FALSE), 
3138                      aopGet(AOP(left),0,FALSE,FALSE), 
3139                      aopGet(AOP(result),0,FALSE,FALSE));
3140       pic14_emitcode("call","genMult8X8_8");
3141
3142     }
3143     genMult8X8_8 (left, right,result);
3144
3145
3146     /* signed or unsigned */
3147     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3148     //l = aopGet(AOP(left),0,FALSE,FALSE);
3149     //MOVA(l);       
3150     //pic14_emitcode("mul","ab");
3151     /* if result size = 1, mul signed = mul unsigned */
3152     //aopPut(AOP(result),"a",0);
3153
3154   } else {  // (size > 1)
3155
3156     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3157                    aopGet(AOP(right),0,FALSE,FALSE), 
3158                    aopGet(AOP(left),0,FALSE,FALSE), 
3159                    aopGet(AOP(result),0,FALSE,FALSE));
3160
3161     if (SPEC_USIGN(opetype)){
3162       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3163       genUMult8X8_16 (left, right, result, NULL);
3164
3165       if (size > 2) {
3166         /* for filling the MSBs */
3167         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3168         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3169       }
3170     }
3171     else{
3172       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3173
3174       pic14_emitcode("mov","a,b");
3175
3176       /* adjust the MSB if left or right neg */
3177
3178       /* if one literal */
3179       if (AOP_TYPE(right) == AOP_LIT){
3180         pic14_emitcode("multiply ","right is a lit");
3181         /* AND literal negative */
3182         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3183           /* adjust MSB (c==0 after mul) */
3184           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3185         }
3186       }
3187       else{
3188         genSMult8X8_16 (left, right, result, NULL);
3189       }
3190
3191       if(size > 2){
3192         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3193         /* get the sign */
3194         pic14_emitcode("rlc","a");
3195         pic14_emitcode("subb","a,acc");
3196       }
3197     }
3198
3199     size -= 2;   
3200     offset = 2;
3201     if (size > 0)
3202       while (size--)
3203         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3204     //aopPut(AOP(result),"a",offset++);
3205   }
3206 }
3207
3208 /*-----------------------------------------------------------------*/
3209 /* genMult - generates code for multiplication                     */
3210 /*-----------------------------------------------------------------*/
3211 static void genMult (iCode *ic)
3212 {
3213     operand *left = IC_LEFT(ic);
3214     operand *right = IC_RIGHT(ic);
3215     operand *result= IC_RESULT(ic);   
3216
3217     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3218     /* assign the amsops */
3219     aopOp (left,ic,FALSE);
3220     aopOp (right,ic,FALSE);
3221     aopOp (result,ic,TRUE);
3222
3223   DEBUGpic14_AopType(__LINE__,left,right,result);
3224
3225     /* special cases first */
3226     /* both are bits */
3227     if (AOP_TYPE(left) == AOP_CRY &&
3228         AOP_TYPE(right)== AOP_CRY) {
3229         genMultbits(left,right,result);
3230         goto release ;
3231     }
3232
3233     /* if both are of size == 1 */
3234     if (AOP_SIZE(left) == 1 &&
3235         AOP_SIZE(right) == 1 ) {
3236         genMultOneByte(left,right,result);
3237         goto release ;
3238     }
3239
3240     pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3241
3242     /* should have been converted to function call */
3243     //assert(0) ;
3244
3245 release :
3246     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3247     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3248     freeAsmop(result,NULL,ic,TRUE); 
3249 }
3250
3251 /*-----------------------------------------------------------------*/
3252 /* genDivbits :- division of bits                                  */
3253 /*-----------------------------------------------------------------*/
3254 static void genDivbits (operand *left, 
3255                         operand *right, 
3256                         operand *result)
3257 {
3258
3259     char *l;
3260
3261     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3262     /* the result must be bit */    
3263     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3264     l = aopGet(AOP(left),0,FALSE,FALSE);
3265
3266     MOVA(l);    
3267
3268     pic14_emitcode("div","ab");
3269     pic14_emitcode("rrc","a");
3270     aopPut(AOP(result),"c",0);
3271 }
3272
3273 /*-----------------------------------------------------------------*/
3274 /* genDivOneByte : 8 bit division                                  */
3275 /*-----------------------------------------------------------------*/
3276 static void genDivOneByte (operand *left,
3277                            operand *right,
3278                            operand *result)
3279 {
3280     sym_link *opetype = operandType(result);
3281     char *l ;
3282     symbol *lbl ;
3283     int size,offset;
3284
3285     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3286     size = AOP_SIZE(result) - 1;
3287     offset = 1;
3288     /* signed or unsigned */
3289     if (SPEC_USIGN(opetype)) {
3290         /* unsigned is easy */
3291         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3292         l = aopGet(AOP(left),0,FALSE,FALSE);
3293         MOVA(l);        
3294         pic14_emitcode("div","ab");
3295         aopPut(AOP(result),"a",0);
3296         while (size--)
3297             aopPut(AOP(result),zero,offset++);
3298         return ;
3299     }
3300
3301     /* signed is a little bit more difficult */
3302
3303     /* save the signs of the operands */
3304     l = aopGet(AOP(left),0,FALSE,FALSE);    
3305     MOVA(l);    
3306     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3307     pic14_emitcode("push","acc"); /* save it on the stack */
3308
3309     /* now sign adjust for both left & right */
3310     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3311     MOVA(l);       
3312     lbl = newiTempLabel(NULL);
3313     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3314     pic14_emitcode("cpl","a");   
3315     pic14_emitcode("inc","a");
3316     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3317     pic14_emitcode("mov","b,a");
3318
3319     /* sign adjust left side */
3320     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3321     MOVA(l);
3322
3323     lbl = newiTempLabel(NULL);
3324     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3325     pic14_emitcode("cpl","a");
3326     pic14_emitcode("inc","a");
3327     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3328
3329     /* now the division */
3330     pic14_emitcode("div","ab");
3331     /* we are interested in the lower order
3332     only */
3333     pic14_emitcode("mov","b,a");
3334     lbl = newiTempLabel(NULL);
3335     pic14_emitcode("pop","acc");   
3336     /* if there was an over flow we don't 
3337     adjust the sign of the result */
3338     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3339     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3340     CLRC;
3341     pic14_emitcode("clr","a");
3342     pic14_emitcode("subb","a,b");
3343     pic14_emitcode("mov","b,a");
3344     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3345
3346     /* now we are done */
3347     aopPut(AOP(result),"b",0);
3348     if(size > 0){
3349         pic14_emitcode("mov","c,b.7");
3350         pic14_emitcode("subb","a,acc");   
3351     }
3352     while (size--)
3353         aopPut(AOP(result),"a",offset++);
3354
3355 }
3356
3357 /*-----------------------------------------------------------------*/
3358 /* genDiv - generates code for division                            */
3359 /*-----------------------------------------------------------------*/
3360 static void genDiv (iCode *ic)
3361 {
3362     operand *left = IC_LEFT(ic);
3363     operand *right = IC_RIGHT(ic);
3364     operand *result= IC_RESULT(ic);   
3365
3366     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3367     /* assign the amsops */
3368     aopOp (left,ic,FALSE);
3369     aopOp (right,ic,FALSE);
3370     aopOp (result,ic,TRUE);
3371
3372     /* special cases first */
3373     /* both are bits */
3374     if (AOP_TYPE(left) == AOP_CRY &&
3375         AOP_TYPE(right)== AOP_CRY) {
3376         genDivbits(left,right,result);
3377         goto release ;
3378     }
3379
3380     /* if both are of size == 1 */
3381     if (AOP_SIZE(left) == 1 &&
3382         AOP_SIZE(right) == 1 ) {
3383         genDivOneByte(left,right,result);
3384         goto release ;
3385     }
3386
3387     /* should have been converted to function call */
3388     assert(0);
3389 release :
3390     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3391     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3392     freeAsmop(result,NULL,ic,TRUE); 
3393 }
3394
3395 /*-----------------------------------------------------------------*/
3396 /* genModbits :- modulus of bits                                   */
3397 /*-----------------------------------------------------------------*/
3398 static void genModbits (operand *left, 
3399                         operand *right, 
3400                         operand *result)
3401 {
3402
3403     char *l;
3404
3405     /* the result must be bit */    
3406     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3407     l = aopGet(AOP(left),0,FALSE,FALSE);
3408
3409     MOVA(l);       
3410
3411     pic14_emitcode("div","ab");
3412     pic14_emitcode("mov","a,b");
3413     pic14_emitcode("rrc","a");
3414     aopPut(AOP(result),"c",0);
3415 }
3416
3417 /*-----------------------------------------------------------------*/
3418 /* genModOneByte : 8 bit modulus                                   */
3419 /*-----------------------------------------------------------------*/
3420 static void genModOneByte (operand *left,
3421                            operand *right,
3422                            operand *result)
3423 {
3424     sym_link *opetype = operandType(result);
3425     char *l ;
3426     symbol *lbl ;
3427
3428     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3429     /* signed or unsigned */
3430     if (SPEC_USIGN(opetype)) {
3431         /* unsigned is easy */
3432         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3433         l = aopGet(AOP(left),0,FALSE,FALSE);
3434         MOVA(l);    
3435         pic14_emitcode("div","ab");
3436         aopPut(AOP(result),"b",0);
3437         return ;
3438     }
3439
3440     /* signed is a little bit more difficult */
3441
3442     /* save the signs of the operands */
3443     l = aopGet(AOP(left),0,FALSE,FALSE);    
3444     MOVA(l);
3445
3446     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3447     pic14_emitcode("push","acc"); /* save it on the stack */
3448
3449     /* now sign adjust for both left & right */
3450     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3451     MOVA(l);
3452
3453     lbl = newiTempLabel(NULL);
3454     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3455     pic14_emitcode("cpl","a");   
3456     pic14_emitcode("inc","a");
3457     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3458     pic14_emitcode("mov","b,a"); 
3459
3460     /* sign adjust left side */
3461     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3462     MOVA(l);
3463
3464     lbl = newiTempLabel(NULL);
3465     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3466     pic14_emitcode("cpl","a");   
3467     pic14_emitcode("inc","a");
3468     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3469
3470     /* now the multiplication */
3471     pic14_emitcode("div","ab");
3472     /* we are interested in the lower order
3473     only */
3474     lbl = newiTempLabel(NULL);
3475     pic14_emitcode("pop","acc");   
3476     /* if there was an over flow we don't 
3477     adjust the sign of the result */
3478     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3479     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3480     CLRC ;
3481     pic14_emitcode("clr","a");
3482     pic14_emitcode("subb","a,b");
3483     pic14_emitcode("mov","b,a");
3484     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3485
3486     /* now we are done */
3487     aopPut(AOP(result),"b",0);
3488
3489 }
3490
3491 /*-----------------------------------------------------------------*/
3492 /* genMod - generates code for division                            */
3493 /*-----------------------------------------------------------------*/
3494 static void genMod (iCode *ic)
3495 {
3496     operand *left = IC_LEFT(ic);
3497     operand *right = IC_RIGHT(ic);
3498     operand *result= IC_RESULT(ic);  
3499
3500     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3501     /* assign the amsops */
3502     aopOp (left,ic,FALSE);
3503     aopOp (right,ic,FALSE);
3504     aopOp (result,ic,TRUE);
3505
3506     /* special cases first */
3507     /* both are bits */
3508     if (AOP_TYPE(left) == AOP_CRY &&
3509         AOP_TYPE(right)== AOP_CRY) {
3510         genModbits(left,right,result);
3511         goto release ;
3512     }
3513
3514     /* if both are of size == 1 */
3515     if (AOP_SIZE(left) == 1 &&
3516         AOP_SIZE(right) == 1 ) {
3517         genModOneByte(left,right,result);
3518         goto release ;
3519     }
3520
3521     /* should have been converted to function call */
3522     assert(0);
3523
3524 release :
3525     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3526     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3527     freeAsmop(result,NULL,ic,TRUE); 
3528 }
3529
3530 /*-----------------------------------------------------------------*/
3531 /* genIfxJump :- will create a jump depending on the ifx           */
3532 /*-----------------------------------------------------------------*/
3533 /*
3534   note: May need to add parameter to indicate when a variable is in bit space.
3535 */
3536 static void genIfxJump (iCode *ic, char *jval)
3537 {
3538
3539     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3540     /* if true label then we jump if condition
3541     supplied is true */
3542     if ( IC_TRUE(ic) ) {
3543
3544         if(strcmp(jval,"a") == 0)
3545           emitSKPZ;
3546         else if (strcmp(jval,"c") == 0)
3547           emitSKPC;
3548         else {
3549           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3550           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3551         }
3552
3553         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3554         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3555
3556     }
3557     else {
3558         /* false label is present */
3559         if(strcmp(jval,"a") == 0)
3560           emitSKPNZ;
3561         else if (strcmp(jval,"c") == 0)
3562           emitSKPNC;
3563         else {
3564           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3565           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3566         }
3567
3568         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3569         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3570
3571     }
3572
3573
3574     /* mark the icode as generated */
3575     ic->generated = 1;
3576 }
3577
3578 /*-----------------------------------------------------------------*/
3579 /* genSkip                                                         */
3580 /*-----------------------------------------------------------------*/
3581 static void genSkip(iCode *ifx,int status_bit)
3582 {
3583   if(!ifx)
3584     return;
3585
3586   if ( IC_TRUE(ifx) ) {
3587     switch(status_bit) {
3588     case 'z':
3589       emitSKPNZ;
3590       break;
3591
3592     case 'c':
3593       emitSKPNC;
3594       break;
3595
3596     case 'd':
3597       emitSKPDC;
3598       break;
3599
3600     }
3601
3602     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3603     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3604
3605   } else {
3606
3607     switch(status_bit) {
3608
3609     case 'z':
3610       emitSKPZ;
3611       break;
3612
3613     case 'c':
3614       emitSKPC;
3615       break;
3616
3617     case 'd':
3618       emitSKPDC;
3619       break;
3620     }
3621     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3622     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3623
3624   }
3625
3626 }
3627
3628 /*-----------------------------------------------------------------*/
3629 /* genSkipc                                                        */
3630 /*-----------------------------------------------------------------*/
3631 static void genSkipc(resolvedIfx *rifx)
3632 {
3633   if(!rifx)
3634     return;
3635
3636   if(rifx->condition)
3637     emitSKPC;
3638   else
3639     emitSKPNC;
3640
3641   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3642   rifx->generated = 1;
3643 }
3644
3645 /*-----------------------------------------------------------------*/
3646 /* genSkipz2                                                       */
3647 /*-----------------------------------------------------------------*/
3648 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3649 {
3650   if(!rifx)
3651     return;
3652
3653   if( (rifx->condition ^ invert_condition) & 1)
3654     emitSKPZ;
3655   else
3656     emitSKPNZ;
3657
3658   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3659   rifx->generated = 1;
3660 }
3661
3662 /*-----------------------------------------------------------------*/
3663 /* genSkipz                                                        */
3664 /*-----------------------------------------------------------------*/
3665 static void genSkipz(iCode *ifx, int condition)
3666 {
3667   if(!ifx)
3668     return;
3669
3670   if(condition)
3671     emitSKPNZ;
3672   else
3673     emitSKPZ;
3674
3675   if ( IC_TRUE(ifx) )
3676     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3677   else
3678     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3679
3680   if ( IC_TRUE(ifx) )
3681     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3682   else
3683     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3684
3685 }
3686 /*-----------------------------------------------------------------*/
3687 /* genSkipCond                                                     */
3688 /*-----------------------------------------------------------------*/
3689 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3690 {
3691   if(!rifx)
3692     return;
3693
3694   if(rifx->condition)
3695     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3696   else
3697     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3698
3699
3700   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3701   rifx->generated = 1;
3702 }
3703
3704 #if 0
3705 /*-----------------------------------------------------------------*/
3706 /* genChkZeroes :- greater or less than comparison                 */
3707 /*     For each byte in a literal that is zero, inclusive or the   */
3708 /*     the corresponding byte in the operand with W                */
3709 /*     returns true if any of the bytes are zero                   */
3710 /*-----------------------------------------------------------------*/
3711 static int genChkZeroes(operand *op, int lit,  int size)
3712 {
3713
3714   int i;
3715   int flag =1;
3716
3717   while(size--) {
3718     i = (lit >> (size*8)) & 0xff;
3719
3720     if(i==0) {
3721       if(flag) 
3722         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3723       else
3724         emitpcode(POC_IORFW, popGet(AOP(op),size));
3725       flag = 0;
3726     }
3727   }
3728
3729   return (flag==0);
3730 }
3731 #endif
3732
3733 /*-----------------------------------------------------------------*/
3734 /* genCmp :- greater or less than comparison                       */
3735 /*-----------------------------------------------------------------*/
3736 static void genCmp (operand *left,operand *right,
3737                     operand *result, iCode *ifx, int sign)
3738 {
3739   int size; //, offset = 0 ;
3740   unsigned long lit = 0L,i = 0;
3741   resolvedIfx rFalseIfx;
3742   //  resolvedIfx rTrueIfx;
3743   symbol *truelbl;
3744   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3745 /*
3746   if(ifx) {
3747     DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3748     DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3749   }
3750 */
3751
3752   resolveIfx(&rFalseIfx,ifx);
3753   truelbl  = newiTempLabel(NULL);
3754   size = max(AOP_SIZE(left),AOP_SIZE(right));
3755
3756   DEBUGpic14_AopType(__LINE__,left,right,result);
3757
3758 #define _swapp
3759
3760   /* if literal is on the right then swap with left */
3761   if ((AOP_TYPE(right) == AOP_LIT)) {
3762     operand *tmp = right ;
3763     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3764     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3765 #ifdef _swapp
3766
3767     lit = (lit - 1) & mask;
3768     right = left;
3769     left = tmp;
3770     rFalseIfx.condition ^= 1;
3771 #endif
3772
3773   } else if ((AOP_TYPE(left) == AOP_LIT)) {
3774     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3775   }
3776
3777
3778   //if(IC_TRUE(ifx) == NULL)
3779   /* if left & right are bit variables */
3780   if (AOP_TYPE(left) == AOP_CRY &&
3781       AOP_TYPE(right) == AOP_CRY ) {
3782     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3783     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3784   } else {
3785     /* subtract right from left if at the
3786        end the carry flag is set then we know that
3787        left is greater than right */
3788
3789     //    {
3790
3791     symbol *lbl  = newiTempLabel(NULL);
3792
3793 #ifndef _swapp
3794     if(AOP_TYPE(right) == AOP_LIT) {
3795
3796       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3797
3798       DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3799
3800       /* special cases */
3801
3802       if(lit == 0) {
3803
3804         if(sign != 0) 
3805           genSkipCond(&rFalseIfx,left,size-1,7);
3806         else 
3807           /* no need to compare to 0...*/
3808           /* NOTE: this is a de-generate compare that most certainly 
3809            *       creates some dead code. */
3810           emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3811
3812         if(ifx) ifx->generated = 1;
3813         return;
3814
3815       }
3816       size--;
3817
3818       if(size == 0) {
3819         //i = (lit >> (size*8)) & 0xff;
3820         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3821         
3822         emitpcode(POC_MOVFW, popGet(AOP(left),size));
3823
3824         i = ((0-lit) & 0xff);
3825         if(sign) {
3826           if( i == 0x81) { 
3827             /* lit is 0x7f, all signed chars are less than
3828              * this except for 0x7f itself */
3829             emitpcode(POC_XORLW, popGetLit(0x7f));
3830             genSkipz2(&rFalseIfx,0);
3831           } else {
3832             emitpcode(POC_ADDLW, popGetLit(0x80));
3833             emitpcode(POC_ADDLW, popGetLit(i^0x80));
3834             genSkipc(&rFalseIfx);
3835           }
3836
3837         } else {
3838           if(lit == 1) {
3839             genSkipz2(&rFalseIfx,1);
3840           } else {
3841             emitpcode(POC_ADDLW, popGetLit(i));
3842             genSkipc(&rFalseIfx);
3843           }
3844         }
3845
3846         if(ifx) ifx->generated = 1;
3847         return;
3848       }
3849
3850       /* chars are out of the way. now do ints and longs */
3851
3852
3853       DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3854         
3855       /* special cases */
3856
3857       if(sign) {
3858
3859         if(lit == 0) {
3860           genSkipCond(&rFalseIfx,left,size,7);
3861           if(ifx) ifx->generated = 1;
3862           return;
3863         }
3864
3865         if(lit <0x100) {
3866           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3867
3868           //rFalseIfx.condition ^= 1;
3869           //genSkipCond(&rFalseIfx,left,size,7);
3870           //rFalseIfx.condition ^= 1;
3871
3872           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3873           if(rFalseIfx.condition)
3874             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3875           else
3876             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3877
3878           emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3879           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3880           emitpcode(POC_MOVFW, popGet(AOP(left),1));
3881
3882           while(size > 1)
3883             emitpcode(POC_IORFW, popGet(AOP(left),size--));
3884
3885           if(rFalseIfx.condition) {
3886             emitSKPZ;
3887             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3888
3889           } else {
3890             emitSKPNZ;
3891           }
3892
3893           genSkipc(&rFalseIfx);
3894           emitpLabel(truelbl->key);
3895           if(ifx) ifx->generated = 1;
3896           return;
3897
3898         }
3899
3900         if(size == 1) {
3901
3902           if( (lit & 0xff) == 0) {
3903             /* lower byte is zero */
3904             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3905             i = ((lit >> 8) & 0xff) ^0x80;
3906             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3907             emitpcode(POC_ADDLW, popGetLit( 0x80));
3908             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3909             genSkipc(&rFalseIfx);
3910
3911
3912             if(ifx) ifx->generated = 1;
3913             return;
3914
3915           }
3916         } else {
3917           /* Special cases for signed longs */
3918           if( (lit & 0xffffff) == 0) {
3919             /* lower byte is zero */
3920             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3921             i = ((lit >> 8*3) & 0xff) ^0x80;
3922             emitpcode(POC_MOVFW, popGet(AOP(left),size));
3923             emitpcode(POC_ADDLW, popGetLit( 0x80));
3924             emitpcode(POC_ADDLW, popGetLit(0x100-i));
3925             genSkipc(&rFalseIfx);
3926
3927
3928             if(ifx) ifx->generated = 1;
3929             return;
3930
3931           }
3932
3933         }
3934
3935
3936         if(lit & (0x80 << (size*8))) {
3937           /* lit is negative */
3938           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3939
3940           //genSkipCond(&rFalseIfx,left,size,7);
3941
3942           emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3943
3944           if(rFalseIfx.condition)
3945             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3946           else
3947             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3948
3949
3950         } else {
3951           /* lit is positive */
3952           DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3953           emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3954           if(rFalseIfx.condition)
3955             emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3956           else
3957             emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3958
3959         }
3960
3961         /*
3962           This works, but is only good for ints.
3963           It also requires a "known zero" register.
3964           emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3965           emitpcode(POC_ADDFW, popGet(AOP(left),0));
3966           emitpcode(POC_RLFW,  popCopyReg(&pc_kzero));
3967           emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
3968           emitpcode(POC_ADDFW, popGet(AOP(left),1));
3969           genSkipc(&rFalseIfx);
3970
3971           emitpLabel(truelbl->key);
3972           if(ifx) ifx->generated = 1;
3973           return;
3974         **/
3975           
3976         /* There are no more special cases, so perform a general compare */
3977   
3978         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3979         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3980
3981         while(size--) {
3982
3983           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3984           emitSKPNZ;
3985           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3986         }
3987         //rFalseIfx.condition ^= 1;
3988         genSkipc(&rFalseIfx);
3989
3990         emitpLabel(truelbl->key);
3991
3992         if(ifx) ifx->generated = 1;
3993         return;
3994
3995
3996       }
3997
3998
3999       /* sign is out of the way. So now do an unsigned compare */
4000       DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4001
4002
4003       /* General case - compare to an unsigned literal on the right.*/
4004
4005       i = (lit >> (size*8)) & 0xff;
4006       emitpcode(POC_MOVLW, popGetLit(i));
4007       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4008       while(size--) {
4009         i = (lit >> (size*8)) & 0xff;
4010
4011         if(i) {
4012           emitpcode(POC_MOVLW, popGetLit(i));
4013           emitSKPNZ;
4014           emitpcode(POC_SUBFW, popGet(AOP(left),size));
4015         } else {
4016           /* this byte of the lit is zero, 
4017            *if it's not the last then OR in the variable */
4018           if(size)
4019             emitpcode(POC_IORFW, popGet(AOP(left),size));
4020         }
4021       }
4022
4023
4024       emitpLabel(lbl->key);
4025       //if(emitFinalCheck)
4026       genSkipc(&rFalseIfx);
4027       if(sign)
4028         emitpLabel(truelbl->key);
4029
4030       if(ifx) ifx->generated = 1;
4031       return;
4032
4033
4034     }
4035 #endif  // _swapp
4036
4037     if(AOP_TYPE(left) == AOP_LIT) {
4038       //symbol *lbl = newiTempLabel(NULL);
4039
4040       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4041
4042
4043       DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4044
4045       /* Special cases */
4046       if((lit == 0) && (sign == 0)){
4047
4048         size--;
4049         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4050         while(size) 
4051           emitpcode(POC_IORFW, popGet(AOP(right),--size));
4052
4053         genSkipz2(&rFalseIfx,0);
4054         if(ifx) ifx->generated = 1;
4055         return;
4056       }
4057
4058       if(size==1) {
4059         /* Special cases */
4060         lit &= 0xff;
4061         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4062           /* degenerate compare can never be true */
4063           if(rFalseIfx.condition == 0)
4064             emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4065
4066           if(ifx) ifx->generated = 1;
4067           return;
4068         }
4069
4070         if(sign) {
4071           /* signed comparisons to a literal byte */
4072
4073           int lp1 = (lit+1) & 0xff;
4074
4075           DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4076           switch (lp1) {
4077           case 0:
4078             rFalseIfx.condition ^= 1;
4079             genSkipCond(&rFalseIfx,right,0,7);
4080             break;
4081           case 0x7f:
4082             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4083             emitpcode(POC_XORLW, popGetLit(0x7f));
4084             genSkipz2(&rFalseIfx,1);
4085             break;
4086           default:
4087             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4088             emitpcode(POC_ADDLW, popGetLit(0x80));
4089             emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4090             rFalseIfx.condition ^= 1;
4091             genSkipc(&rFalseIfx);
4092             break;
4093           }
4094           if(ifx) ifx->generated = 1;
4095         } else {
4096           /* unsigned comparisons to a literal byte */
4097
4098           switch(lit & 0xff ) {
4099           case 0:
4100             emitpcode(POC_MOVFW, popGet(AOP(right),0));
4101             genSkipz2(&rFalseIfx,0);
4102             if(ifx) ifx->generated = 1;
4103             break;
4104           case 0x7f:
4105             rFalseIfx.condition ^= 1;
4106             genSkipCond(&rFalseIfx,right,0,7);
4107             if(ifx) ifx->generated = 1;
4108             break;
4109
4110           default:
4111             emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4112             emitpcode(POC_SUBFW, popGet(AOP(right),0));
4113             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4114             rFalseIfx.condition ^= 1;
4115             if (AOP_TYPE(result) == AOP_CRY) {
4116               genSkipc(&rFalseIfx);
4117               if(ifx) ifx->generated = 1;
4118             } else {
4119               DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4120               emitpcode(POC_CLRF, popGet(AOP(result),0));
4121               emitpcode(POC_RLF, popGet(AOP(result),0));
4122               emitpcode(POC_MOVLW, popGetLit(0x01));
4123               emitpcode(POC_XORWF, popGet(AOP(result),0));
4124             }         
4125             break;
4126           }
4127         }
4128
4129         //goto check_carry;
4130         return;
4131
4132       } else {
4133
4134         /* Size is greater than 1 */
4135
4136         if(sign) {
4137           int lp1 = lit+1;
4138
4139           size--;
4140
4141           if(lp1 == 0) {
4142             /* this means lit = 0xffffffff, or -1 */
4143
4144
4145             DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4146             rFalseIfx.condition ^= 1;
4147             genSkipCond(&rFalseIfx,right,size,7);
4148             if(ifx) ifx->generated = 1;
4149             return;
4150           }
4151
4152           if(lit == 0) {
4153             int s = size;
4154
4155             if(rFalseIfx.condition) {
4156               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4157               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4158             }
4159
4160             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4161             while(size--)
4162               emitpcode(POC_IORFW, popGet(AOP(right),size));
4163
4164
4165             emitSKPZ;
4166             if(rFalseIfx.condition) {
4167               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4168               emitpLabel(truelbl->key);
4169             }else {
4170               rFalseIfx.condition ^= 1;
4171               genSkipCond(&rFalseIfx,right,s,7);
4172             }
4173
4174             if(ifx) ifx->generated = 1;
4175             return;
4176           }
4177
4178           if((size == 1) &&  (0 == (lp1&0xff))) {
4179             /* lower byte of signed word is zero */
4180             DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4181             i = ((lp1 >> 8) & 0xff) ^0x80;
4182             emitpcode(POC_MOVFW, popGet(AOP(right),size));
4183             emitpcode(POC_ADDLW, popGetLit( 0x80));
4184             emitpcode(POC_ADDLW, popGetLit(0x100-i));
4185             rFalseIfx.condition ^= 1;
4186             genSkipc(&rFalseIfx);
4187
4188
4189             if(ifx) ifx->generated = 1;
4190             return;
4191           }
4192
4193           if(lit & (0x80 << (size*8))) {
4194             /* Lit is less than zero */
4195             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4196             //rFalseIfx.condition ^= 1;
4197             //genSkipCond(&rFalseIfx,left,size,7);
4198             //rFalseIfx.condition ^= 1;
4199             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4200             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4201
4202             if(rFalseIfx.condition)
4203               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4204             else
4205               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4206
4207
4208           } else {
4209             /* Lit is greater than or equal to zero */
4210             DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4211             //rFalseIfx.condition ^= 1;
4212             //genSkipCond(&rFalseIfx,right,size,7);
4213             //rFalseIfx.condition ^= 1;
4214
4215             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4216             //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4217
4218             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4219             if(rFalseIfx.condition)
4220               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4221             else
4222               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4223
4224           }
4225
4226
4227           emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4228           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4229
4230           while(size--) {
4231
4232             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4233             emitSKPNZ;
4234             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4235           }
4236           rFalseIfx.condition ^= 1;
4237           //rFalseIfx.condition = 1;
4238           genSkipc(&rFalseIfx);
4239
4240           emitpLabel(truelbl->key);
4241
4242           if(ifx) ifx->generated = 1;
4243           return;
4244           // end of if (sign)
4245         } else {
4246
4247           /* compare word or long to an unsigned literal on the right.*/
4248
4249
4250           size--;
4251           if(lit < 0xff) {
4252             DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4253             switch (lit) {
4254             case 0:
4255               break; /* handled above */
4256 /*
4257             case 0xff:
4258               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4259               while(size--)
4260                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4261               genSkipz2(&rFalseIfx,0);
4262               break;
4263 */
4264             default:
4265               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4266               while(--size)
4267                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4268
4269               emitSKPZ;
4270               if(rFalseIfx.condition)
4271                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4272               else
4273                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4274
4275
4276               emitpcode(POC_MOVLW, popGetLit(lit+1));
4277               emitpcode(POC_SUBFW, popGet(AOP(right),0));
4278
4279               rFalseIfx.condition ^= 1;
4280               genSkipc(&rFalseIfx);
4281             }
4282
4283             emitpLabel(truelbl->key);
4284
4285             if(ifx) ifx->generated = 1;
4286             return;
4287           }
4288
4289
4290           lit++;
4291           DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4292           i = (lit >> (size*8)) & 0xff;
4293
4294           emitpcode(POC_MOVLW, popGetLit(i));
4295           emitpcode(POC_SUBFW, popGet(AOP(right),size));
4296
4297           while(size--) {
4298             i = (lit >> (size*8)) & 0xff;
4299
4300             if(i) {
4301               emitpcode(POC_MOVLW, popGetLit(i));
4302               emitSKPNZ;
4303               emitpcode(POC_SUBFW, popGet(AOP(right),size));
4304             } else {
4305               /* this byte of the lit is zero, 
4306                *if it's not the last then OR in the variable */
4307               if(size)
4308                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4309             }
4310           }
4311
4312
4313           emitpLabel(lbl->key);
4314
4315           rFalseIfx.condition ^= 1;
4316           genSkipc(&rFalseIfx);
4317         }
4318
4319         if(sign)
4320           emitpLabel(truelbl->key);
4321         if(ifx) ifx->generated = 1;
4322         return;
4323       }
4324     }
4325     /* Compare two variables */
4326
4327     DEBUGpic14_emitcode(";sign","%d",sign);
4328
4329     size--;
4330     if(sign) {
4331       /* Sigh. thus sucks... */
4332       if(size) {
4333         emitpcode(POC_MOVFW, popGet(AOP(left),size));
4334         emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4335         emitpcode(POC_MOVLW, popGetLit(0x80));
4336         emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4337         emitpcode(POC_XORFW, popGet(AOP(right),size));
4338         emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4339       } else {
4340         /* Signed char comparison */
4341         /* Special thanks to Nikolai Golovchenko for this snippet */
4342         emitpcode(POC_MOVFW, popGet(AOP(right),0));
4343         emitpcode(POC_SUBFW, popGet(AOP(left),0));
4344         emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4345         emitpcode(POC_XORFW, popGet(AOP(left),0));
4346         emitpcode(POC_XORFW, popGet(AOP(right),0));
4347         emitpcode(POC_ADDLW, popGetLit(0x80));
4348
4349         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4350         genSkipc(&rFalseIfx);
4351           
4352         if(ifx) ifx->generated = 1;
4353         return;
4354       }
4355
4356     } else {
4357
4358       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4359       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4360     }
4361
4362
4363     /* The rest of the bytes of a multi-byte compare */
4364     while (size) {
4365
4366       emitSKPZ;
4367       emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4368       size--;
4369
4370       emitpcode(POC_MOVFW, popGet(AOP(right),size));
4371       emitpcode(POC_SUBFW, popGet(AOP(left),size));
4372
4373
4374     }
4375
4376     emitpLabel(lbl->key);
4377
4378     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4379     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4380         (AOP_TYPE(result) == AOP_REG)) {
4381       emitpcode(POC_CLRF, popGet(AOP(result),0));
4382       emitpcode(POC_RLF, popGet(AOP(result),0));
4383     } else {
4384       genSkipc(&rFalseIfx);
4385     }         
4386     //genSkipc(&rFalseIfx);
4387     if(ifx) ifx->generated = 1;
4388
4389     return;
4390
4391   }
4392
4393   // check_carry:
4394   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4395     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4396     pic14_outBitC(result);
4397   } else {
4398     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4399     /* if the result is used in the next
4400        ifx conditional branch then generate
4401        code a little differently */
4402     if (ifx )
4403       genIfxJump (ifx,"c");
4404     else
4405       pic14_outBitC(result);
4406     /* leave the result in acc */
4407   }
4408
4409 }
4410
4411 /*-----------------------------------------------------------------*/
4412 /* genCmpGt :- greater than comparison                             */
4413 /*-----------------------------------------------------------------*/
4414 static void genCmpGt (iCode *ic, iCode *ifx)
4415 {
4416     operand *left, *right, *result;
4417     sym_link *letype , *retype;
4418     int sign ;
4419
4420     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4421     left = IC_LEFT(ic);
4422     right= IC_RIGHT(ic);
4423     result = IC_RESULT(ic);
4424
4425     letype = getSpec(operandType(left));
4426     retype =getSpec(operandType(right));
4427     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4428     /* assign the amsops */
4429     aopOp (left,ic,FALSE);
4430     aopOp (right,ic,FALSE);
4431     aopOp (result,ic,TRUE);
4432
4433     genCmp(right, left, result, ifx, sign);
4434
4435     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4436     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4437     freeAsmop(result,NULL,ic,TRUE); 
4438 }
4439
4440 /*-----------------------------------------------------------------*/
4441 /* genCmpLt - less than comparisons                                */
4442 /*-----------------------------------------------------------------*/
4443 static void genCmpLt (iCode *ic, iCode *ifx)
4444 {
4445     operand *left, *right, *result;
4446     sym_link *letype , *retype;
4447     int sign ;
4448
4449     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4450     left = IC_LEFT(ic);
4451     right= IC_RIGHT(ic);
4452     result = IC_RESULT(ic);
4453
4454     letype = getSpec(operandType(left));
4455     retype =getSpec(operandType(right));
4456     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4457
4458     /* assign the amsops */
4459     aopOp (left,ic,FALSE);
4460     aopOp (right,ic,FALSE);
4461     aopOp (result,ic,TRUE);
4462
4463     genCmp(left, right, result, ifx, sign);
4464
4465     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4466     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4467     freeAsmop(result,NULL,ic,TRUE); 
4468 }
4469
4470 /*-----------------------------------------------------------------*/
4471 /* genc16bit2lit - compare a 16 bit value to a literal             */
4472 /*-----------------------------------------------------------------*/
4473 static void genc16bit2lit(operand *op, int lit, int offset)
4474 {
4475   int i;
4476
4477   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4478   if( (lit&0xff) == 0) 
4479     i=1;
4480   else
4481     i=0;
4482
4483   switch( BYTEofLONG(lit,i)) { 
4484   case 0:
4485     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4486     break;
4487   case 1:
4488     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4489     break;
4490   case 0xff:
4491     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4492     break;
4493   default:
4494     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4495     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4496   }
4497
4498   i ^= 1;
4499
4500   switch( BYTEofLONG(lit,i)) { 
4501   case 0:
4502     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4503     break;
4504   case 1:
4505     emitSKPNZ;
4506     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4507     break;
4508   case 0xff:
4509     emitSKPNZ;
4510     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4511     break;
4512   default:
4513     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4514     emitSKPNZ;
4515     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4516
4517   }
4518
4519 }
4520
4521 /*-----------------------------------------------------------------*/
4522 /* gencjneshort - compare and jump if not equal                    */
4523 /*-----------------------------------------------------------------*/
4524 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4525 {
4526   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4527   int offset = 0;
4528   int res_offset = 0;  /* the result may be a different size then left or right */
4529   int res_size = AOP_SIZE(result);
4530   resolvedIfx rIfx;
4531   symbol *lbl;
4532
4533   unsigned long lit = 0L;
4534   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4535   DEBUGpic14_AopType(__LINE__,left,right,result);
4536   if(result)
4537     DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4538   resolveIfx(&rIfx,ifx);
4539   lbl =  newiTempLabel(NULL);
4540
4541
4542   /* if the left side is a literal or 
4543      if the right is in a pointer register and left 
4544      is not */
4545   if ((AOP_TYPE(left) == AOP_LIT) || 
4546       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4547     operand *t = right;
4548     right = left;
4549     left = t;
4550   }
4551   if(AOP_TYPE(right) == AOP_LIT)
4552     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4553
4554   /* if the right side is a literal then anything goes */
4555   if (AOP_TYPE(right) == AOP_LIT &&
4556       AOP_TYPE(left) != AOP_DIR ) {
4557     switch(size) {
4558     case 2:
4559       genc16bit2lit(left, lit, 0);
4560       emitSKPNZ;
4561       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4562       break;
4563     default:
4564       while (size--) {
4565         if(lit & 0xff) {
4566           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4567           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4568         } else {
4569           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4570         }
4571
4572         emitSKPNZ;
4573         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4574         offset++;
4575         if(res_offset < res_size-1)
4576           res_offset++;
4577         lit >>= 8;
4578       }
4579       break;
4580     }
4581   }
4582
4583   /* if the right side is in a register or in direct space or
4584      if the left is a pointer register & right is not */    
4585   else if (AOP_TYPE(right) == AOP_REG ||
4586            AOP_TYPE(right) == AOP_DIR || 
4587            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4588            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4589     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4590     int lbl_key = lbl->key;
4591
4592     if(result) {
4593       emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4594       //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4595     }else {
4596       DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4597       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4598               __FUNCTION__,__LINE__);
4599       return;
4600     }
4601
4602 /*     switch(size) { */
4603 /*     case 2: */
4604 /*       genc16bit2lit(left, lit, 0); */
4605 /*       emitSKPNZ; */
4606 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4607 /*       break; */
4608 /*     default: */
4609     while (size--) {
4610       int emit_skip=1;
4611       if((AOP_TYPE(left) == AOP_DIR) && 
4612          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4613
4614         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4615         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4616
4617       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4618             
4619         switch (lit & 0xff) {
4620         case 0:
4621           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4622           break;
4623         case 1:
4624           emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4625           emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4626           //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4627           emit_skip=0;
4628           break;
4629         case 0xff:
4630           emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4631           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4632           //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4633           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4634           emit_skip=0;
4635           break;
4636         default:
4637           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4638           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4639         }
4640         lit >>= 8;
4641
4642       } else {
4643         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4644       }
4645       if(emit_skip) {
4646         if(AOP_TYPE(result) == AOP_CRY) {
4647           pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4648           if(rIfx.condition)
4649             emitSKPNZ;
4650           else
4651             emitSKPZ;
4652           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4653         } else {
4654           /* fix me. probably need to check result size too */
4655           //emitpcode(POC_CLRF,popGet(AOP(result),0));
4656           if(rIfx.condition)
4657             emitSKPZ;
4658           else
4659             emitSKPNZ;
4660           emitpcode(POC_GOTO,popGetLabel(lbl_key));
4661           //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4662         }
4663         if(ifx)
4664           ifx->generated=1;
4665       }
4666       emit_skip++;
4667       offset++;
4668       if(res_offset < res_size-1)
4669         res_offset++;
4670     }
4671 /*       break; */
4672 /*     } */
4673   } else if(AOP_TYPE(right) == AOP_REG &&
4674             AOP_TYPE(left) != AOP_DIR){
4675
4676     while(size--) {
4677       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4678       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4679       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4680       if(rIfx.condition)
4681         emitSKPNZ;
4682       else
4683         emitSKPZ;
4684       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4685       offset++;
4686       if(res_offset < res_size-1)
4687         res_offset++;
4688     }
4689       
4690   }else{
4691     /* right is a pointer reg need both a & b */
4692     while(size--) {
4693       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4694       if(strcmp(l,"b"))
4695         pic14_emitcode("mov","b,%s",l);
4696       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4697       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4698       offset++;
4699     }
4700   }
4701
4702   emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4703   if(!rIfx.condition)
4704     emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4705
4706   emitpLabel(lbl->key);
4707
4708   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4709
4710   if(ifx)
4711     ifx->generated = 1;
4712 }
4713
4714 #if 0
4715 /*-----------------------------------------------------------------*/
4716 /* gencjne - compare and jump if not equal                         */
4717 /*-----------------------------------------------------------------*/
4718 static void gencjne(operand *left, operand *right, iCode *ifx)
4719 {
4720     symbol *tlbl  = newiTempLabel(NULL);
4721
4722     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4723     gencjneshort(left, right, lbl);
4724
4725     pic14_emitcode("mov","a,%s",one);
4726     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4727     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4728     pic14_emitcode("clr","a");
4729     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4730
4731     emitpLabel(lbl->key);
4732     emitpLabel(tlbl->key);
4733
4734 }
4735 #endif
4736
4737 /*-----------------------------------------------------------------*/
4738 /* genCmpEq - generates code for equal to                          */
4739 /*-----------------------------------------------------------------*/
4740 static void genCmpEq (iCode *ic, iCode *ifx)
4741 {
4742     operand *left, *right, *result;
4743     unsigned long lit = 0L;
4744     int size,offset=0;
4745
4746     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4747
4748     if(ifx)
4749       DEBUGpic14_emitcode ("; ifx is non-null","");
4750     else
4751       DEBUGpic14_emitcode ("; ifx is null","");
4752
4753     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4754     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4755     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4756
4757     size = max(AOP_SIZE(left),AOP_SIZE(right));
4758
4759     DEBUGpic14_AopType(__LINE__,left,right,result);
4760
4761     /* if literal, literal on the right or 
4762     if the right is in a pointer register and left 
4763     is not */
4764     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4765         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4766       operand *tmp = right ;
4767       right = left;
4768       left = tmp;
4769     }
4770
4771
4772     if(ifx && !AOP_SIZE(result)){
4773         symbol *tlbl;
4774         /* if they are both bit variables */
4775         if (AOP_TYPE(left) == AOP_CRY &&
4776             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4777             if(AOP_TYPE(right) == AOP_LIT){
4778                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4779                 if(lit == 0L){
4780                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4781                     pic14_emitcode("cpl","c");
4782                 } else if(lit == 1L) {
4783                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4784                 } else {
4785                     pic14_emitcode("clr","c");
4786                 }
4787                 /* AOP_TYPE(right) == AOP_CRY */
4788             } else {
4789                 symbol *lbl = newiTempLabel(NULL);
4790                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4791                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4792                 pic14_emitcode("cpl","c");
4793                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4794             }
4795             /* if true label then we jump if condition
4796             supplied is true */
4797             tlbl = newiTempLabel(NULL);
4798             if ( IC_TRUE(ifx) ) {
4799                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4800                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4801             } else {
4802                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4803                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4804             }
4805             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4806
4807             {
4808               /* left and right are both bit variables, result is carry */
4809               resolvedIfx rIfx;
4810               
4811               resolveIfx(&rIfx,ifx);
4812
4813               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4814               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4815               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4816               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4817               genSkipz2(&rIfx,0);
4818             }
4819         } else {
4820
4821           /* They're not both bit variables. Is the right a literal? */
4822           if(AOP_TYPE(right) == AOP_LIT) {
4823             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4824             
4825             switch(size) {
4826
4827             case 1:
4828               switch(lit & 0xff) {
4829               case 1:
4830                 if ( IC_TRUE(ifx) ) {
4831                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4832                   emitSKPNZ;
4833                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4834                 } else {
4835                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4836                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4837                 }
4838                 break;
4839               case 0xff:
4840                 if ( IC_TRUE(ifx) ) {
4841                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4842                   emitSKPNZ;
4843                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4844                 } else {
4845                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4846                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4847                 }
4848                 break;
4849               default:
4850                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4851                 if(lit)
4852                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4853                 genSkip(ifx,'z');
4854               }
4855
4856
4857               /* end of size == 1 */
4858               break;
4859               
4860             case 2:
4861               genc16bit2lit(left,lit,offset);
4862               genSkip(ifx,'z');
4863               break;
4864               /* end of size == 2 */
4865
4866             default:
4867               /* size is 4 */
4868               if(lit==0) {
4869                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4870                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4871                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4872                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4873
4874               } else {
4875
4876                 /* search for patterns that can be optimized */
4877
4878                 genc16bit2lit(left,lit,0);
4879                 lit >>= 16;
4880                 if(lit) {
4881                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4882                   //genSkip(ifx,'z');
4883                   genc16bit2lit(left,lit,2);
4884                 } else {
4885                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4886                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4887
4888                 }
4889                 
4890               }
4891
4892               genSkip(ifx,'z');
4893             }
4894           
4895             ifx->generated = 1;
4896             goto release ;
4897             
4898
4899           } else if(AOP_TYPE(right) == AOP_CRY ) {
4900             /* we know the left is not a bit, but that the right is */
4901             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4902             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4903                       popGet(AOP(right),offset));
4904             emitpcode(POC_XORLW,popGetLit(1));
4905
4906             /* if the two are equal, then W will be 0 and the Z bit is set
4907              * we could test Z now, or go ahead and check the high order bytes if
4908              * the variable we're comparing is larger than a byte. */
4909
4910             while(--size)
4911               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4912
4913             if ( IC_TRUE(ifx) ) {
4914               emitSKPNZ;
4915               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4916               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4917             } else {
4918               emitSKPZ;
4919               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4920               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4921             }
4922
4923           } else {
4924             /* They're both variables that are larger than bits */
4925             int s = size;
4926
4927             tlbl = newiTempLabel(NULL);
4928
4929             while(size--) {
4930               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4931               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4932
4933               if ( IC_TRUE(ifx) ) {
4934                 if(size) {
4935                   emitSKPZ;
4936                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4937                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4938                 } else {
4939                   emitSKPNZ;
4940                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4941                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4942                 }
4943               } else {
4944                 emitSKPZ;
4945                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4946                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4947               }
4948               offset++;
4949             }
4950             if(s>1 && IC_TRUE(ifx)) {
4951               emitpLabel(tlbl->key);
4952               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4953             }
4954           }
4955         }
4956         /* mark the icode as generated */
4957         ifx->generated = 1;
4958         goto release ;
4959     }
4960
4961     /* if they are both bit variables */
4962     if (AOP_TYPE(left) == AOP_CRY &&
4963         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4964         if(AOP_TYPE(right) == AOP_LIT){
4965             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4966             if(lit == 0L){
4967                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4968                 pic14_emitcode("cpl","c");
4969             } else if(lit == 1L) {
4970                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4971             } else {
4972                 pic14_emitcode("clr","c");
4973             }
4974             /* AOP_TYPE(right) == AOP_CRY */
4975         } else {
4976             symbol *lbl = newiTempLabel(NULL);
4977             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4978             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4979             pic14_emitcode("cpl","c");
4980             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4981         }
4982         /* c = 1 if egal */
4983         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4984             pic14_outBitC(result);
4985             goto release ;
4986         }
4987         if (ifx) {
4988             genIfxJump (ifx,"c");
4989             goto release ;
4990         }
4991         /* if the result is used in an arithmetic operation
4992         then put the result in place */
4993         pic14_outBitC(result);
4994     } else {
4995       
4996       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4997       gencjne(left,right,result,ifx);
4998 /*
4999       if(ifx) 
5000         gencjne(left,right,newiTempLabel(NULL));
5001       else {
5002         if(IC_TRUE(ifx)->key)
5003           gencjne(left,right,IC_TRUE(ifx)->key);
5004         else
5005           gencjne(left,right,IC_FALSE(ifx)->key);
5006         ifx->generated = 1;
5007         goto release ;
5008       }
5009       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5010         aopPut(AOP(result),"a",0);
5011         goto release ;
5012       }
5013
5014       if (ifx) {
5015         genIfxJump (ifx,"a");
5016         goto release ;
5017       }
5018 */
5019       /* if the result is used in an arithmetic operation
5020          then put the result in place */
5021 /*
5022       if (AOP_TYPE(result) != AOP_CRY) 
5023         pic14_outAcc(result);
5024 */
5025       /* leave the result in acc */
5026     }
5027
5028 release:
5029     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5030     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5031     freeAsmop(result,NULL,ic,TRUE);
5032 }
5033
5034 /*-----------------------------------------------------------------*/
5035 /* ifxForOp - returns the icode containing the ifx for operand     */
5036 /*-----------------------------------------------------------------*/
5037 static iCode *ifxForOp ( operand *op, iCode *ic )
5038 {
5039     /* if true symbol then needs to be assigned */
5040     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5041     if (IS_TRUE_SYMOP(op))
5042         return NULL ;
5043
5044     /* if this has register type condition and
5045     the next instruction is ifx with the same operand
5046     and live to of the operand is upto the ifx only then */
5047     if (ic->next &&
5048         ic->next->op == IFX &&
5049         IC_COND(ic->next)->key == op->key &&
5050         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5051         return ic->next;
5052
5053     if (ic->next &&
5054         ic->next->op == IFX &&
5055         IC_COND(ic->next)->key == op->key) {
5056       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5057       return ic->next;
5058     }
5059
5060     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5061     if (ic->next &&
5062         ic->next->op == IFX)
5063       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5064
5065     if (ic->next &&
5066         ic->next->op == IFX &&
5067         IC_COND(ic->next)->key == op->key) {
5068       DEBUGpic14_emitcode ("; "," key is okay");
5069       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5070                            OP_SYMBOL(op)->liveTo,
5071                            ic->next->seq);
5072     }
5073
5074
5075     return NULL;
5076 }
5077 /*-----------------------------------------------------------------*/
5078 /* genAndOp - for && operation                                     */
5079 /*-----------------------------------------------------------------*/
5080 static void genAndOp (iCode *ic)
5081 {
5082     operand *left,*right, *result;
5083 /*     symbol *tlbl; */
5084
5085     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5086     /* note here that && operations that are in an
5087     if statement are taken away by backPatchLabels
5088     only those used in arthmetic operations remain */
5089     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5090     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5091     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5092
5093     DEBUGpic14_AopType(__LINE__,left,right,result);
5094
5095     emitpcode(POC_MOVFW,popGet(AOP(left),0));
5096     emitpcode(POC_ANDFW,popGet(AOP(right),0));
5097     emitpcode(POC_MOVWF,popGet(AOP(result),0));
5098
5099     /* if both are bit variables */
5100 /*     if (AOP_TYPE(left) == AOP_CRY && */
5101 /*         AOP_TYPE(right) == AOP_CRY ) { */
5102 /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5103 /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5104 /*         pic14_outBitC(result); */
5105 /*     } else { */
5106 /*         tlbl = newiTempLabel(NULL); */
5107 /*         pic14_toBoolean(left);     */
5108 /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5109 /*         pic14_toBoolean(right); */
5110 /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5111 /*         pic14_outBitAcc(result); */
5112 /*     } */
5113
5114     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5115     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5116     freeAsmop(result,NULL,ic,TRUE);
5117 }
5118
5119
5120 /*-----------------------------------------------------------------*/
5121 /* genOrOp - for || operation                                      */
5122 /*-----------------------------------------------------------------*/
5123 /*
5124   tsd pic port -
5125   modified this code, but it doesn't appear to ever get called
5126 */
5127
5128 static void genOrOp (iCode *ic)
5129 {
5130     operand *left,*right, *result;
5131     symbol *tlbl;
5132
5133     /* note here that || operations that are in an
5134     if statement are taken away by backPatchLabels
5135     only those used in arthmetic operations remain */
5136     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5137     aopOp((left=IC_LEFT(ic)),ic,FALSE);
5138     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5139     aopOp((result=IC_RESULT(ic)),ic,FALSE);
5140
5141     DEBUGpic14_AopType(__LINE__,left,right,result);
5142
5143     /* if both are bit variables */
5144     if (AOP_TYPE(left) == AOP_CRY &&
5145         AOP_TYPE(right) == AOP_CRY ) {
5146       pic14_emitcode("clrc","");
5147       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5148                AOP(left)->aopu.aop_dir,
5149                AOP(left)->aopu.aop_dir);
5150       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5151                AOP(right)->aopu.aop_dir,
5152                AOP(right)->aopu.aop_dir);
5153       pic14_emitcode("setc","");
5154
5155     } else {
5156         tlbl = newiTempLabel(NULL);
5157         pic14_toBoolean(left);
5158         emitSKPZ;
5159         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5160         pic14_toBoolean(right);
5161         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5162
5163         pic14_outBitAcc(result);
5164     }
5165
5166     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5167     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5168     freeAsmop(result,NULL,ic,TRUE);            
5169 }
5170
5171 /*-----------------------------------------------------------------*/
5172 /* isLiteralBit - test if lit == 2^n                               */
5173 /*-----------------------------------------------------------------*/
5174 static int isLiteralBit(unsigned long lit)
5175 {
5176     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5177     0x100L,0x200L,0x400L,0x800L,
5178     0x1000L,0x2000L,0x4000L,0x8000L,
5179     0x10000L,0x20000L,0x40000L,0x80000L,
5180     0x100000L,0x200000L,0x400000L,0x800000L,
5181     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5182     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5183     int idx;
5184     
5185     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5186     for(idx = 0; idx < 32; idx++)
5187         if(lit == pw[idx])
5188             return idx+1;
5189     return 0;
5190 }
5191
5192 /*-----------------------------------------------------------------*/
5193 /* continueIfTrue -                                                */
5194 /*-----------------------------------------------------------------*/
5195 static void continueIfTrue (iCode *ic)
5196 {
5197     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5198     if(IC_TRUE(ic))
5199         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5200     ic->generated = 1;
5201 }
5202
5203 /*-----------------------------------------------------------------*/
5204 /* jmpIfTrue -                                                     */
5205 /*-----------------------------------------------------------------*/
5206 static void jumpIfTrue (iCode *ic)
5207 {
5208     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5209     if(!IC_TRUE(ic))
5210         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5211     ic->generated = 1;
5212 }
5213
5214 /*-----------------------------------------------------------------*/
5215 /* jmpTrueOrFalse -                                                */
5216 /*-----------------------------------------------------------------*/
5217 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5218 {
5219     // ugly but optimized by peephole
5220     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5221     if(IC_TRUE(ic)){
5222         symbol *nlbl = newiTempLabel(NULL);
5223         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5224         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5225         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5226         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5227     }
5228     else{
5229         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5230         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5231     }
5232     ic->generated = 1;
5233 }
5234
5235 /*-----------------------------------------------------------------*/
5236 /* genAnd  - code for and                                          */
5237 /*-----------------------------------------------------------------*/
5238 static void genAnd (iCode *ic, iCode *ifx)
5239 {
5240   operand *left, *right, *result;
5241   int size, offset=0;  
5242   unsigned long lit = 0L;
5243   int bytelit = 0;
5244   resolvedIfx rIfx;
5245
5246
5247   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5248   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5249   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5250   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5251
5252   resolveIfx(&rIfx,ifx);
5253
5254   /* if left is a literal & right is not then exchange them */
5255   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5256       AOP_NEEDSACC(left)) {
5257     operand *tmp = right ;
5258     right = left;
5259     left = tmp;
5260   }
5261
5262   /* if result = right then exchange them */
5263   if(pic14_sameRegs(AOP(result),AOP(right))){
5264     operand *tmp = right ;
5265     right = left;
5266     left = tmp;
5267   }
5268
5269   /* if right is bit then exchange them */
5270   if (AOP_TYPE(right) == AOP_CRY &&
5271       AOP_TYPE(left) != AOP_CRY){
5272     operand *tmp = right ;
5273     right = left;
5274     left = tmp;
5275   }
5276   if(AOP_TYPE(right) == AOP_LIT)
5277     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5278
5279   size = AOP_SIZE(result);
5280
5281   DEBUGpic14_AopType(__LINE__,left,right,result);
5282
5283   // if(bit & yy)
5284   // result = bit & yy;
5285   if (AOP_TYPE(left) == AOP_CRY){
5286     // c = bit & literal;
5287     if(AOP_TYPE(right) == AOP_LIT){
5288       if(lit & 1) {
5289         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5290           // no change
5291           goto release;
5292         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5293       } else {
5294         // bit(result) = 0;
5295         if(size && (AOP_TYPE(result) == AOP_CRY)){
5296           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5297           goto release;
5298         }
5299         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5300           jumpIfTrue(ifx);
5301           goto release;
5302         }
5303         pic14_emitcode("clr","c");
5304       }
5305     } else {
5306       if (AOP_TYPE(right) == AOP_CRY){
5307         // c = bit & bit;
5308         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5309         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5310       } else {
5311         // c = bit & val;
5312         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5313         // c = lsb
5314         pic14_emitcode("rrc","a");
5315         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5316       }
5317     }
5318     // bit = c
5319     // val = c
5320     if(size)
5321       pic14_outBitC(result);
5322     // if(bit & ...)
5323     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5324       genIfxJump(ifx, "c");           
5325     goto release ;
5326   }
5327
5328   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5329   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5330   if((AOP_TYPE(right) == AOP_LIT) &&
5331      (AOP_TYPE(result) == AOP_CRY) &&
5332      (AOP_TYPE(left) != AOP_CRY)){
5333     int posbit = isLiteralBit(lit);
5334     /* left &  2^n */
5335     if(posbit){
5336       posbit--;
5337       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5338       // bit = left & 2^n
5339       if(size)
5340         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5341       // if(left &  2^n)
5342       else{
5343         if(ifx){
5344 /*
5345           if(IC_TRUE(ifx)) {
5346             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5347             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
5348           } else {
5349             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5350             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
5351           }
5352 */
5353           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5354                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5355           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5356           
5357           ifx->generated = 1;
5358         }
5359         goto release;
5360       }
5361     } else {
5362       symbol *tlbl = newiTempLabel(NULL);
5363       int sizel = AOP_SIZE(left);
5364       if(size)
5365         pic14_emitcode("setb","c");
5366       while(sizel--){
5367         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5368           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5369           // byte ==  2^n ?
5370           if((posbit = isLiteralBit(bytelit)) != 0)
5371             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5372           else{
5373             if(bytelit != 0x0FFL)
5374               pic14_emitcode("anl","a,%s",
5375                              aopGet(AOP(right),offset,FALSE,TRUE));
5376             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5377           }
5378         }
5379         offset++;
5380       }
5381       // bit = left & literal
5382       if(size){
5383         pic14_emitcode("clr","c");
5384         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5385       }
5386       // if(left & literal)
5387       else{
5388         if(ifx)
5389           jmpTrueOrFalse(ifx, tlbl);
5390         goto release ;
5391       }
5392     }
5393     pic14_outBitC(result);
5394     goto release ;
5395   }
5396
5397   /* if left is same as result */
5398   if(pic14_sameRegs(AOP(result),AOP(left))){
5399     int know_W = -1;
5400     for(;size--; offset++,lit>>=8) {
5401       if(AOP_TYPE(right) == AOP_LIT){
5402         switch(lit & 0xff) {
5403         case 0x00:
5404           /*  and'ing with 0 has clears the result */
5405           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5406           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5407           break;
5408         case 0xff:
5409           /* and'ing with 0xff is a nop when the result and left are the same */
5410           break;
5411
5412         default:
5413           {
5414             int p = my_powof2( (~lit) & 0xff );
5415             if(p>=0) {
5416               /* only one bit is set in the literal, so use a bcf instruction */
5417               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5418               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5419
5420             } else {
5421               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5422               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5423               if(know_W != (int)(lit&0xff))
5424                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5425               know_W = lit &0xff;
5426               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5427             }
5428           }    
5429         }
5430       } else {
5431         if (AOP_TYPE(left) == AOP_ACC) {
5432           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5433         } else {                    
5434           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5435           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5436
5437         }
5438       }
5439     }
5440
5441   } else {
5442     // left & result in different registers
5443     if(AOP_TYPE(result) == AOP_CRY){
5444       // result = bit
5445       // if(size), result in bit
5446       // if(!size && ifx), conditional oper: if(left & right)
5447       symbol *tlbl = newiTempLabel(NULL);
5448       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5449       if(size)
5450         pic14_emitcode("setb","c");
5451       while(sizer--){
5452         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5453         pic14_emitcode("anl","a,%s",
5454                        aopGet(AOP(left),offset,FALSE,FALSE));
5455         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5456         offset++;
5457       }
5458       if(size){
5459         CLRC;
5460         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5461         pic14_outBitC(result);
5462       } else if(ifx)
5463         jmpTrueOrFalse(ifx, tlbl);
5464     } else {
5465       for(;(size--);offset++) {
5466         // normal case
5467         // result = left & right
5468         if(AOP_TYPE(right) == AOP_LIT){
5469           int t = (lit >> (offset*8)) & 0x0FFL;
5470           switch(t) { 
5471           case 0x00:
5472             pic14_emitcode("clrf","%s",
5473                            aopGet(AOP(result),offset,FALSE,FALSE));
5474             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5475             break;
5476           case 0xff:
5477             if(AOP_TYPE(left) != AOP_ACC) {
5478               pic14_emitcode("movf","%s,w",
5479                              aopGet(AOP(left),offset,FALSE,FALSE));
5480               pic14_emitcode("movwf","%s",
5481                              aopGet(AOP(result),offset,FALSE,FALSE));
5482               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5483             }
5484             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5485             break;
5486           default:
5487             if(AOP_TYPE(left) == AOP_ACC) {
5488               emitpcode(POC_ANDLW, popGetLit(t));
5489             } else {
5490               pic14_emitcode("movlw","0x%x",t);
5491               pic14_emitcode("andwf","%s,w",
5492                              aopGet(AOP(left),offset,FALSE,FALSE));
5493               pic14_emitcode("movwf","%s",
5494                              aopGet(AOP(result),offset,FALSE,FALSE));
5495               
5496               emitpcode(POC_MOVLW, popGetLit(t));
5497               emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5498             }
5499             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5500           }
5501           continue;
5502         }
5503
5504         if (AOP_TYPE(left) == AOP_ACC) {
5505           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5506           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5507         } else {
5508           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5509           pic14_emitcode("andwf","%s,w",
5510                          aopGet(AOP(left),offset,FALSE,FALSE));
5511           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5512           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5513         }
5514         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5515         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5516       }
5517     }
5518   }
5519
5520   release :
5521     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5522   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5523   freeAsmop(result,NULL,ic,TRUE);     
5524 }
5525
5526 /*-----------------------------------------------------------------*/
5527 /* genOr  - code for or                                            */
5528 /*-----------------------------------------------------------------*/
5529 static void genOr (iCode *ic, iCode *ifx)
5530 {
5531     operand *left, *right, *result;
5532     int size, offset=0;
5533     unsigned long lit = 0L;
5534
5535     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5536
5537     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5538     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5539     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5540
5541     DEBUGpic14_AopType(__LINE__,left,right,result);
5542
5543     /* if left is a literal & right is not then exchange them */
5544     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5545         AOP_NEEDSACC(left)) {
5546         operand *tmp = right ;
5547         right = left;
5548         left = tmp;
5549     }
5550
5551     /* if result = right then exchange them */
5552     if(pic14_sameRegs(AOP(result),AOP(right))){
5553         operand *tmp = right ;
5554         right = left;
5555         left = tmp;
5556     }
5557
5558     /* if right is bit then exchange them */
5559     if (AOP_TYPE(right) == AOP_CRY &&
5560         AOP_TYPE(left) != AOP_CRY){
5561         operand *tmp = right ;
5562         right = left;
5563         left = tmp;
5564     }
5565
5566     DEBUGpic14_AopType(__LINE__,left,right,result);
5567
5568     if(AOP_TYPE(right) == AOP_LIT)
5569         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5570
5571     size = AOP_SIZE(result);
5572
5573     // if(bit | yy)
5574     // xx = bit | yy;
5575     if (AOP_TYPE(left) == AOP_CRY){
5576         if(AOP_TYPE(right) == AOP_LIT){
5577             // c = bit & literal;
5578             if(lit){
5579                 // lit != 0 => result = 1
5580                 if(AOP_TYPE(result) == AOP_CRY){
5581                   if(size)
5582                     emitpcode(POC_BSF, popGet(AOP(result),0));
5583                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5584                   //     AOP(result)->aopu.aop_dir,
5585                   //     AOP(result)->aopu.aop_dir);
5586                     else if(ifx)
5587                         continueIfTrue(ifx);
5588                     goto release;
5589                 }
5590             } else {
5591                 // lit == 0 => result = left
5592                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5593                     goto release;
5594                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5595             }
5596         } else {
5597             if (AOP_TYPE(right) == AOP_CRY){
5598               if(pic14_sameRegs(AOP(result),AOP(left))){
5599                 // c = bit | bit;
5600                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5601                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5602                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5603
5604                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5605                          AOP(result)->aopu.aop_dir,
5606                          AOP(result)->aopu.aop_dir);
5607                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5608                          AOP(right)->aopu.aop_dir,
5609                          AOP(right)->aopu.aop_dir);
5610                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5611                          AOP(result)->aopu.aop_dir,
5612                          AOP(result)->aopu.aop_dir);
5613               } else {
5614                 if( AOP_TYPE(result) == AOP_ACC) {
5615                   emitpcode(POC_MOVLW, popGetLit(0));
5616                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5617                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5618                   emitpcode(POC_MOVLW, popGetLit(1));
5619
5620                 } else {
5621
5622                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5623                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5624                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5625                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5626
5627                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5628                                  AOP(result)->aopu.aop_dir,
5629                                  AOP(result)->aopu.aop_dir);
5630                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5631                                  AOP(right)->aopu.aop_dir,
5632                                  AOP(right)->aopu.aop_dir);
5633                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5634                                  AOP(left)->aopu.aop_dir,
5635                                  AOP(left)->aopu.aop_dir);
5636                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5637                                  AOP(result)->aopu.aop_dir,
5638                                  AOP(result)->aopu.aop_dir);
5639                 }
5640               }
5641             } else {
5642                 // c = bit | val;
5643                 symbol *tlbl = newiTempLabel(NULL);
5644                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5645
5646
5647                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5648                 if( AOP_TYPE(right) == AOP_ACC) {
5649                   emitpcode(POC_IORLW, popGetLit(0));
5650                   emitSKPNZ;
5651                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5652                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5653                 }
5654
5655
5656
5657                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5658                     pic14_emitcode(";XXX setb","c");
5659                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5660                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5661                 pic14_toBoolean(right);
5662                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5663                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5664                     jmpTrueOrFalse(ifx, tlbl);
5665                     goto release;
5666                 } else {
5667                     CLRC;
5668                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5669                 }
5670             }
5671         }
5672         // bit = c
5673         // val = c
5674         if(size)
5675             pic14_outBitC(result);
5676         // if(bit | ...)
5677         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5678             genIfxJump(ifx, "c");           
5679         goto release ;
5680     }
5681
5682     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5683     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5684     if((AOP_TYPE(right) == AOP_LIT) &&
5685        (AOP_TYPE(result) == AOP_CRY) &&
5686        (AOP_TYPE(left) != AOP_CRY)){
5687         if(lit){
5688           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5689             // result = 1
5690             if(size)
5691                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5692             else 
5693                 continueIfTrue(ifx);
5694             goto release;
5695         } else {
5696           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5697             // lit = 0, result = boolean(left)
5698             if(size)
5699                 pic14_emitcode(";XXX setb","c");
5700             pic14_toBoolean(right);
5701             if(size){
5702                 symbol *tlbl = newiTempLabel(NULL);
5703                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5704                 CLRC;
5705                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5706             } else {
5707                 genIfxJump (ifx,"a");
5708                 goto release;
5709             }
5710         }
5711         pic14_outBitC(result);
5712         goto release ;
5713     }
5714
5715     /* if left is same as result */
5716     if(pic14_sameRegs(AOP(result),AOP(left))){
5717       int know_W = -1;
5718       for(;size--; offset++,lit>>=8) {
5719         if(AOP_TYPE(right) == AOP_LIT){
5720           if((lit & 0xff) == 0)
5721             /*  or'ing with 0 has no effect */
5722             continue;
5723           else {
5724             int p = my_powof2(lit & 0xff);
5725             if(p>=0) {
5726               /* only one bit is set in the literal, so use a bsf instruction */
5727               emitpcode(POC_BSF,
5728                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5729             } else {
5730               if(know_W != (int)(lit & 0xff))
5731                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5732               know_W = lit & 0xff;
5733               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5734             }
5735                     
5736           }
5737         } else {
5738           if (AOP_TYPE(left) == AOP_ACC) {
5739             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5740             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5741           } else {                  
5742             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5743             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5744
5745             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5746             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5747
5748           }
5749         }
5750       }
5751     } else {
5752         // left & result in different registers
5753         if(AOP_TYPE(result) == AOP_CRY){
5754             // result = bit
5755             // if(size), result in bit
5756             // if(!size && ifx), conditional oper: if(left | right)
5757             symbol *tlbl = newiTempLabel(NULL);
5758             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5759             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5760
5761
5762             if(size)
5763                 pic14_emitcode(";XXX setb","c");
5764             while(sizer--){
5765                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5766                 pic14_emitcode(";XXX orl","a,%s",
5767                          aopGet(AOP(left),offset,FALSE,FALSE));
5768                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5769                 offset++;
5770             }
5771             if(size){
5772                 CLRC;
5773                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5774                 pic14_outBitC(result);
5775             } else if(ifx)
5776                 jmpTrueOrFalse(ifx, tlbl);
5777         } else for(;(size--);offset++){
5778           // normal case
5779           // result = left & right
5780           if(AOP_TYPE(right) == AOP_LIT){
5781             int t = (lit >> (offset*8)) & 0x0FFL;
5782             switch(t) { 
5783             case 0x00:
5784               if (AOP_TYPE(left) != AOP_ACC) {
5785                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5786               }
5787               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5788
5789               break;
5790             default:
5791               if (AOP_TYPE(left) == AOP_ACC) {
5792                 emitpcode(POC_IORLW,  popGetLit(t));
5793               } else {
5794                 emitpcode(POC_MOVLW,  popGetLit(t));
5795                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5796               }
5797               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));              
5798             }
5799             continue;
5800           }
5801
5802           // faster than result <- left, anl result,right
5803           // and better if result is SFR
5804           if (AOP_TYPE(left) == AOP_ACC) {
5805             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5806             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5807           } else {
5808             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5809             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5810
5811             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5812             pic14_emitcode("iorwf","%s,w",
5813                      aopGet(AOP(left),offset,FALSE,FALSE));
5814           }
5815           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5816           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5817         }
5818     }
5819
5820 release :
5821     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5822     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5823     freeAsmop(result,NULL,ic,TRUE);     
5824 }
5825
5826 /*-----------------------------------------------------------------*/
5827 /* genXor - code for xclusive or                                   */
5828 /*-----------------------------------------------------------------*/
5829 static void genXor (iCode *ic, iCode *ifx)
5830 {
5831   operand *left, *right, *result;
5832   int size, offset=0;
5833   unsigned long lit = 0L;
5834
5835   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5836
5837   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5838   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5839   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5840
5841   /* if left is a literal & right is not ||
5842      if left needs acc & right does not */
5843   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5844       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5845     operand *tmp = right ;
5846     right = left;
5847     left = tmp;
5848   }
5849
5850   /* if result = right then exchange them */
5851   if(pic14_sameRegs(AOP(result),AOP(right))){
5852     operand *tmp = right ;
5853     right = left;
5854     left = tmp;
5855   }
5856
5857   /* if right is bit then exchange them */
5858   if (AOP_TYPE(right) == AOP_CRY &&
5859       AOP_TYPE(left) != AOP_CRY){
5860     operand *tmp = right ;
5861     right = left;
5862     left = tmp;
5863   }
5864   if(AOP_TYPE(right) == AOP_LIT)
5865     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5866
5867   size = AOP_SIZE(result);
5868
5869   // if(bit ^ yy)
5870   // xx = bit ^ yy;
5871   if (AOP_TYPE(left) == AOP_CRY){
5872     if(AOP_TYPE(right) == AOP_LIT){
5873       // c = bit & literal;
5874       if(lit>>1){
5875         // lit>>1  != 0 => result = 1
5876         if(AOP_TYPE(result) == AOP_CRY){
5877           if(size)
5878             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5879             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5880           else if(ifx)
5881             continueIfTrue(ifx);
5882           goto release;
5883         }
5884         pic14_emitcode("setb","c");
5885       } else{
5886         // lit == (0 or 1)
5887         if(lit == 0){
5888           // lit == 0, result = left
5889           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5890             goto release;
5891           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5892         } else{
5893           // lit == 1, result = not(left)
5894           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5895             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5896             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5897             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5898             goto release;
5899           } else {
5900             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5901             pic14_emitcode("cpl","c");
5902           }
5903         }
5904       }
5905
5906     } else {
5907       // right != literal
5908       symbol *tlbl = newiTempLabel(NULL);
5909       if (AOP_TYPE(right) == AOP_CRY){
5910         // c = bit ^ bit;
5911         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5912       }
5913       else{
5914         int sizer = AOP_SIZE(right);
5915         // c = bit ^ val
5916         // if val>>1 != 0, result = 1
5917         pic14_emitcode("setb","c");
5918         while(sizer){
5919           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5920           if(sizer == 1)
5921             // test the msb of the lsb
5922             pic14_emitcode("anl","a,#0xfe");
5923           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5924           sizer--;
5925         }
5926         // val = (0,1)
5927         pic14_emitcode("rrc","a");
5928       }
5929       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5930       pic14_emitcode("cpl","c");
5931       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5932     }
5933     // bit = c
5934     // val = c
5935     if(size)
5936       pic14_outBitC(result);
5937     // if(bit | ...)
5938     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5939       genIfxJump(ifx, "c");           
5940     goto release ;
5941   }
5942
5943   if(pic14_sameRegs(AOP(result),AOP(left))){
5944     /* if left is same as result */
5945     for(;size--; offset++) {
5946       if(AOP_TYPE(right) == AOP_LIT){
5947         int t  = (lit >> (offset*8)) & 0x0FFL;
5948         if(t == 0x00L)
5949           continue;
5950         else
5951           if (IS_AOP_PREG(left)) {
5952             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5953             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5954             aopPut(AOP(result),"a",offset);
5955           } else {
5956             emitpcode(POC_MOVLW, popGetLit(t));
5957             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5958             pic14_emitcode("xrl","%s,%s",
5959                            aopGet(AOP(left),offset,FALSE,TRUE),
5960                            aopGet(AOP(right),offset,FALSE,FALSE));
5961           }
5962       } else {
5963         if (AOP_TYPE(left) == AOP_ACC)
5964           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5965         else {
5966           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5967           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5968 /*
5969           if (IS_AOP_PREG(left)) {
5970             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5971             aopPut(AOP(result),"a",offset);
5972           } else
5973             pic14_emitcode("xrl","%s,a",
5974                            aopGet(AOP(left),offset,FALSE,TRUE));
5975 */
5976         }
5977       }
5978     }
5979   } else {
5980     // left & result in different registers
5981     if(AOP_TYPE(result) == AOP_CRY){
5982       // result = bit
5983       // if(size), result in bit
5984       // if(!size && ifx), conditional oper: if(left ^ right)
5985       symbol *tlbl = newiTempLabel(NULL);
5986       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5987       if(size)
5988         pic14_emitcode("setb","c");
5989       while(sizer--){
5990         if((AOP_TYPE(right) == AOP_LIT) &&
5991            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5992           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5993         } else {
5994           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5995           pic14_emitcode("xrl","a,%s",
5996                          aopGet(AOP(left),offset,FALSE,FALSE));
5997         }
5998         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5999         offset++;
6000       }
6001       if(size){
6002         CLRC;
6003         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6004         pic14_outBitC(result);
6005       } else if(ifx)
6006         jmpTrueOrFalse(ifx, tlbl);
6007     } else for(;(size--);offset++){
6008       // normal case
6009       // result = left & right
6010       if(AOP_TYPE(right) == AOP_LIT){
6011         int t = (lit >> (offset*8)) & 0x0FFL;
6012         switch(t) { 
6013         case 0x00:
6014           if (AOP_TYPE(left) != AOP_ACC) {
6015             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6016           }
6017           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6018           pic14_emitcode("movf","%s,w",
6019                          aopGet(AOP(left),offset,FALSE,FALSE));
6020           pic14_emitcode("movwf","%s",
6021                          aopGet(AOP(result),offset,FALSE,FALSE));
6022           break;
6023         case 0xff:
6024           if (AOP_TYPE(left) == AOP_ACC) {
6025             emitpcode(POC_XORLW, popGetLit(t));
6026           } else {
6027             emitpcode(POC_COMFW,popGet(AOP(left),offset));
6028           }
6029           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6030           break;
6031         default:
6032           if (AOP_TYPE(left) == AOP_ACC) {
6033             emitpcode(POC_XORLW, popGetLit(t));
6034           } else {
6035             emitpcode(POC_MOVLW, popGetLit(t));
6036             emitpcode(POC_XORFW,popGet(AOP(left),offset));
6037           }
6038           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6039           pic14_emitcode("movlw","0x%x",t);
6040           pic14_emitcode("xorwf","%s,w",
6041                          aopGet(AOP(left),offset,FALSE,FALSE));
6042           pic14_emitcode("movwf","%s",
6043                          aopGet(AOP(result),offset,FALSE,FALSE));
6044
6045         }
6046         continue;
6047       }
6048
6049       // faster than result <- left, anl result,right
6050       // and better if result is SFR
6051       if (AOP_TYPE(left) == AOP_ACC) {
6052         emitpcode(POC_XORFW,popGet(AOP(right),offset));
6053         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6054       } else {
6055         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6056         emitpcode(POC_XORFW,popGet(AOP(left),offset));
6057         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6058         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
6059       }
6060       if ( AOP_TYPE(result) != AOP_ACC){
6061         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6062         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
6063       }
6064     }
6065   }
6066
6067   release :
6068     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6069   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6070   freeAsmop(result,NULL,ic,TRUE);     
6071 }
6072
6073 /*-----------------------------------------------------------------*/
6074 /* genInline - write the inline code out                           */
6075 /*-----------------------------------------------------------------*/
6076 static void genInline (iCode *ic)
6077 {
6078     char *buffer, *bp, *bp1;
6079     
6080     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6081
6082     _G.inLine += (!options.asmpeep);
6083
6084     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6085     strcpy(buffer,IC_INLINE(ic));
6086
6087     /* emit each line as a code */
6088     while (*bp) {
6089         if (*bp == '\n') {
6090             *bp++ = '\0';
6091
6092             if(*bp1)
6093               addpCode2pBlock(pb,AssembleLine(bp1));
6094             bp1 = bp;
6095         } else {
6096             if (*bp == ':') {
6097                 bp++;
6098                 *bp = '\0';
6099                 bp++;
6100                 pic14_emitcode(bp1,"");
6101                 bp1 = bp;
6102             } else
6103                 bp++;
6104         }
6105     }
6106     if ((bp1 != bp) && *bp1)
6107       addpCode2pBlock(pb,AssembleLine(bp1));
6108
6109     Safe_free(buffer);
6110
6111     _G.inLine -= (!options.asmpeep);
6112 }
6113
6114 /*-----------------------------------------------------------------*/
6115 /* genRRC - rotate right with carry                                */
6116 /*-----------------------------------------------------------------*/
6117 static void genRRC (iCode *ic)
6118 {
6119   operand *left , *result ;
6120   int size, offset = 0, same;
6121
6122   /* rotate right with carry */
6123   left = IC_LEFT(ic);
6124   result=IC_RESULT(ic);
6125   aopOp (left,ic,FALSE);
6126   aopOp (result,ic,FALSE);
6127
6128   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6129
6130   same = pic14_sameRegs(AOP(result),AOP(left));
6131
6132   size = AOP_SIZE(result);    
6133
6134   /* get the lsb and put it into the carry */
6135   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6136
6137   offset = 0 ;
6138
6139   while(size--) {
6140
6141     if(same) {
6142       emitpcode(POC_RRF, popGet(AOP(left),offset));
6143     } else {
6144       emitpcode(POC_RRFW, popGet(AOP(left),offset));
6145       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6146     }
6147
6148     offset++;
6149   }
6150
6151   freeAsmop(left,NULL,ic,TRUE);
6152   freeAsmop(result,NULL,ic,TRUE);
6153 }
6154
6155 /*-----------------------------------------------------------------*/
6156 /* genRLC - generate code for rotate left with carry               */
6157 /*-----------------------------------------------------------------*/
6158 static void genRLC (iCode *ic)
6159 {    
6160   operand *left , *result ;
6161   int size, offset = 0;
6162   int same;
6163
6164   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6165   /* rotate right with carry */
6166   left = IC_LEFT(ic);
6167   result=IC_RESULT(ic);
6168   aopOp (left,ic,FALSE);
6169   aopOp (result,ic,FALSE);
6170
6171   DEBUGpic14_AopType(__LINE__,left,NULL,result);
6172
6173   same = pic14_sameRegs(AOP(result),AOP(left));
6174
6175   /* move it to the result */
6176   size = AOP_SIZE(result);    
6177
6178   /* get the msb and put it into the carry */
6179   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6180
6181   offset = 0 ;
6182
6183   while(size--) {
6184
6185     if(same) {
6186       emitpcode(POC_RLF, popGet(AOP(left),offset));
6187     } else {
6188       emitpcode(POC_RLFW, popGet(AOP(left),offset));
6189       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6190     }
6191
6192     offset++;
6193   }
6194
6195
6196   freeAsmop(left,NULL,ic,TRUE);
6197   freeAsmop(result,NULL,ic,TRUE);
6198 }
6199
6200 /*-----------------------------------------------------------------*/
6201 /* genGetHbit - generates code get highest order bit               */
6202 /*-----------------------------------------------------------------*/
6203 static void genGetHbit (iCode *ic)
6204 {
6205     operand *left, *result;
6206     left = IC_LEFT(ic);
6207     result=IC_RESULT(ic);
6208     aopOp (left,ic,FALSE);
6209     aopOp (result,ic,FALSE);
6210
6211     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6212     /* get the highest order byte into a */
6213     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6214     if(AOP_TYPE(result) == AOP_CRY){
6215         pic14_emitcode("rlc","a");
6216         pic14_outBitC(result);
6217     }
6218     else{
6219         pic14_emitcode("rl","a");
6220         pic14_emitcode("anl","a,#0x01");
6221         pic14_outAcc(result);
6222     }
6223
6224
6225     freeAsmop(left,NULL,ic,TRUE);
6226     freeAsmop(result,NULL,ic,TRUE);
6227 }
6228
6229 /*-----------------------------------------------------------------*/
6230 /* AccRol - rotate left accumulator by known count                 */
6231 /*-----------------------------------------------------------------*/
6232 static void AccRol (int shCount)
6233 {
6234     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6235     shCount &= 0x0007;              // shCount : 0..7
6236     switch(shCount){
6237         case 0 :
6238             break;
6239         case 1 :
6240             pic14_emitcode("rl","a");
6241             break;
6242         case 2 :
6243             pic14_emitcode("rl","a");
6244             pic14_emitcode("rl","a");
6245             break;
6246         case 3 :
6247             pic14_emitcode("swap","a");
6248             pic14_emitcode("rr","a");
6249             break;
6250         case 4 :
6251             pic14_emitcode("swap","a");
6252             break;
6253         case 5 :
6254             pic14_emitcode("swap","a");
6255             pic14_emitcode("rl","a");
6256             break;
6257         case 6 :
6258             pic14_emitcode("rr","a");
6259             pic14_emitcode("rr","a");
6260             break;
6261         case 7 :
6262             pic14_emitcode("rr","a");
6263             break;
6264     }
6265 }
6266
6267 /*-----------------------------------------------------------------*/
6268 /* AccLsh - left shift accumulator by known count                  */
6269 /*-----------------------------------------------------------------*/
6270 static void AccLsh (int shCount)
6271 {
6272     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6273     if(shCount != 0){
6274         if(shCount == 1)
6275             pic14_emitcode("add","a,acc");
6276         else 
6277             if(shCount == 2) {
6278             pic14_emitcode("add","a,acc");
6279             pic14_emitcode("add","a,acc");
6280         } else {
6281             /* rotate left accumulator */
6282             AccRol(shCount);
6283             /* and kill the lower order bits */
6284             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6285         }
6286     }
6287 }
6288
6289 /*-----------------------------------------------------------------*/
6290 /* AccRsh - right shift accumulator by known count                 */
6291 /*-----------------------------------------------------------------*/
6292 static void AccRsh (int shCount)
6293 {
6294     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6295     if(shCount != 0){
6296         if(shCount == 1){
6297             CLRC;
6298             pic14_emitcode("rrc","a");
6299         } else {
6300             /* rotate right accumulator */
6301             AccRol(8 - shCount);
6302             /* and kill the higher order bits */
6303             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6304         }
6305     }
6306 }
6307
6308 #if 0
6309 /*-----------------------------------------------------------------*/
6310 /* AccSRsh - signed right shift accumulator by known count                 */
6311 /*-----------------------------------------------------------------*/
6312 static void AccSRsh (int shCount)
6313 {
6314     symbol *tlbl ;
6315     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6316     if(shCount != 0){
6317         if(shCount == 1){
6318             pic14_emitcode("mov","c,acc.7");
6319             pic14_emitcode("rrc","a");
6320         } else if(shCount == 2){
6321             pic14_emitcode("mov","c,acc.7");
6322             pic14_emitcode("rrc","a");
6323             pic14_emitcode("mov","c,acc.7");
6324             pic14_emitcode("rrc","a");
6325         } else {
6326             tlbl = newiTempLabel(NULL);
6327             /* rotate right accumulator */
6328             AccRol(8 - shCount);
6329             /* and kill the higher order bits */
6330             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6331             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6332             pic14_emitcode("orl","a,#0x%02x",
6333                      (unsigned char)~SRMask[shCount]);
6334             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6335         }
6336     }
6337 }
6338 #endif
6339 /*-----------------------------------------------------------------*/
6340 /* shiftR1Left2Result - shift right one byte from left to result   */
6341 /*-----------------------------------------------------------------*/
6342 static void shiftR1Left2ResultSigned (operand *left, int offl,
6343                                 operand *result, int offr,
6344                                 int shCount)
6345 {
6346   int same;
6347
6348   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6349
6350   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6351
6352   switch(shCount) {
6353   case 1:
6354     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6355     if(same) 
6356       emitpcode(POC_RRF, popGet(AOP(result),offr));
6357     else {
6358       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6359       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6360     }
6361
6362     break;
6363   case 2:
6364
6365     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6366     if(same) 
6367       emitpcode(POC_RRF, popGet(AOP(result),offr));
6368     else {
6369       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6370       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6371     }
6372     emitpcode(POC_RLFW, popGet(AOP(result),offr));
6373     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6374
6375     break;
6376
6377   case 3:
6378     if(same)
6379       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6380     else {
6381       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6382       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6383     }
6384
6385     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6386     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6387     emitpcode(POC_ANDLW, popGetLit(0x1f));
6388
6389     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6390     emitpcode(POC_IORLW, popGetLit(0xe0));
6391
6392     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6393     break;
6394
6395   case 4:
6396     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6397     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6398     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6399     emitpcode(POC_IORLW,  popGetLit(0xf0));
6400     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6401     break;
6402   case 5:
6403     if(same) {
6404       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6405     } else {
6406       emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6407       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6408     }
6409     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6410     emitpcode(POC_ANDLW,  popGetLit(0x07));
6411     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6412     emitpcode(POC_IORLW,  popGetLit(0xf8));
6413     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6414     break;
6415
6416   case 6:
6417     if(same) {
6418       emitpcode(POC_MOVLW, popGetLit(0x00));
6419       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6420       emitpcode(POC_MOVLW, popGetLit(0xfe));
6421       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6422       emitpcode(POC_IORLW, popGetLit(0x01));
6423       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6424     } else {
6425       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6426       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6427       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6428       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6429       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6430     }
6431     break;
6432
6433   case 7:
6434     if(same) {
6435       emitpcode(POC_MOVLW, popGetLit(0x00));
6436       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6437       emitpcode(POC_MOVLW, popGetLit(0xff));
6438       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6439     } else {
6440       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6441       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6442       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6443     }
6444
6445   default:
6446     break;
6447   }
6448 }
6449
6450 /*-----------------------------------------------------------------*/
6451 /* shiftR1Left2Result - shift right one byte from left to result   */
6452 /*-----------------------------------------------------------------*/
6453 static void shiftR1Left2Result (operand *left, int offl,
6454                                 operand *result, int offr,
6455                                 int shCount, int sign)
6456 {
6457   int same;
6458
6459   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6460
6461   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6462
6463   /* Copy the msb into the carry if signed. */
6464   if(sign) {
6465     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6466     return;
6467   }
6468
6469
6470
6471   switch(shCount) {
6472   case 1:
6473     emitCLRC;
6474     if(same) 
6475       emitpcode(POC_RRF, popGet(AOP(result),offr));
6476     else {
6477       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6478       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6479     }
6480     break;
6481   case 2:
6482     emitCLRC;
6483     if(same) {
6484       emitpcode(POC_RRF, popGet(AOP(result),offr));
6485     } else {
6486       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6487       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6488     }
6489     emitCLRC;
6490     emitpcode(POC_RRF, popGet(AOP(result),offr));
6491
6492     break;
6493   case 3:
6494     if(same)
6495       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6496     else {
6497       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6498       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6499     }
6500
6501     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6502     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6503     emitpcode(POC_ANDLW, popGetLit(0x1f));
6504     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6505     break;
6506       
6507   case 4:
6508     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6509     emitpcode(POC_ANDLW, popGetLit(0x0f));
6510     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6511     break;
6512
6513   case 5:
6514     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6515     emitpcode(POC_ANDLW, popGetLit(0x0f));
6516     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6517     emitCLRC;
6518     emitpcode(POC_RRF, popGet(AOP(result),offr));
6519
6520     break;
6521   case 6:
6522
6523     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6524     emitpcode(POC_ANDLW, popGetLit(0x80));
6525     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6526     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6527     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6528     break;
6529
6530   case 7:
6531
6532     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6533     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6534     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6535
6536     break;
6537
6538   default:
6539     break;
6540   }
6541 }
6542
6543 /*-----------------------------------------------------------------*/
6544 /* shiftL1Left2Result - shift left one byte from left to result    */
6545 /*-----------------------------------------------------------------*/
6546 static void shiftL1Left2Result (operand *left, int offl,
6547                                 operand *result, int offr, int shCount)
6548 {
6549   int same;
6550
6551   //    char *l;
6552   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6553
6554   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6555   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6556     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6557     //    MOVA(l);
6558     /* shift left accumulator */
6559     //AccLsh(shCount); // don't comment out just yet...
6560   //    aopPut(AOP(result),"a",offr);
6561
6562   switch(shCount) {
6563   case 1:
6564     /* Shift left 1 bit position */
6565     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6566     if(same) {
6567       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6568     } else {
6569       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6570       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6571     }
6572     break;
6573   case 2:
6574     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6575     emitpcode(POC_ANDLW,popGetLit(0x7e));
6576     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6577     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6578     break;
6579   case 3:
6580     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6581     emitpcode(POC_ANDLW,popGetLit(0x3e));
6582     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6583     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6584     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6585     break;
6586   case 4:
6587     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6588     emitpcode(POC_ANDLW, popGetLit(0xf0));
6589     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6590     break;
6591   case 5:
6592     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6593     emitpcode(POC_ANDLW, popGetLit(0xf0));
6594     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6595     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6596     break;
6597   case 6:
6598     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6599     emitpcode(POC_ANDLW, popGetLit(0x30));
6600     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6601     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6602     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6603     break;
6604   case 7:
6605     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6606     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6607     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6608     break;
6609
6610   default:
6611     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6612   }
6613
6614 }
6615
6616 /*-----------------------------------------------------------------*/
6617 /* movLeft2Result - move byte from left to result                  */
6618 /*-----------------------------------------------------------------*/
6619 static void movLeft2Result (operand *left, int offl,
6620                             operand *result, int offr)
6621 {
6622   char *l;
6623   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6624   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6625     l = aopGet(AOP(left),offl,FALSE,FALSE);
6626
6627     if (*l == '@' && (IS_AOP_PREG(result))) {
6628       pic14_emitcode("mov","a,%s",l);
6629       aopPut(AOP(result),"a",offr);
6630     } else {
6631       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6632       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6633     }
6634   }
6635 }
6636
6637 /*-----------------------------------------------------------------*/
6638 /* shiftL2Left2Result - shift left two bytes from left to result   */
6639 /*-----------------------------------------------------------------*/
6640 static void shiftL2Left2Result (operand *left, int offl,
6641                                 operand *result, int offr, int shCount)
6642 {
6643
6644
6645   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6646
6647   if(pic14_sameRegs(AOP(result), AOP(left))) {
6648     switch(shCount) {
6649     case 0:
6650       break;
6651     case 1:
6652     case 2:
6653     case 3:
6654
6655       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6656       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6657       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6658
6659       while(--shCount) {
6660         emitCLRC;
6661         emitpcode(POC_RLF, popGet(AOP(result),offr));
6662         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6663       }
6664
6665       break;
6666     case 4:
6667     case 5:
6668       emitpcode(POC_MOVLW, popGetLit(0x0f));
6669       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6670       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6671       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6672       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6673       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6674       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6675       if(shCount >=5) {
6676         emitpcode(POC_RLF, popGet(AOP(result),offr));
6677         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6678       }
6679       break;
6680     case 6:
6681       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6682       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6683       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6684       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6685       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6686       emitpcode(POC_ANDLW,popGetLit(0xc0));
6687       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6688       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6689       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6690       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6691       break;
6692     case 7:
6693       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6694       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6695       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6696       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6697       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6698     }
6699
6700   } else {
6701     switch(shCount) {
6702     case 0:
6703       break;
6704     case 1:
6705     case 2:
6706     case 3:
6707       /* note, use a mov/add for the shift since the mov has a
6708          chance of getting optimized out */
6709       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6710       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6711       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6712       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6713       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6714
6715       while(--shCount) {
6716         emitCLRC;
6717         emitpcode(POC_RLF, popGet(AOP(result),offr));
6718         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6719       }
6720       break;
6721
6722     case 4:
6723     case 5:
6724       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6725       emitpcode(POC_ANDLW, popGetLit(0xF0));
6726       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6727       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6728       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6729       emitpcode(POC_ANDLW, popGetLit(0xF0));
6730       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6731       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6732
6733
6734       if(shCount == 5) {
6735         emitpcode(POC_RLF, popGet(AOP(result),offr));
6736         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6737       }
6738       break;
6739     case 6:
6740       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6741       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6742       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6743       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6744
6745       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6746       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6747       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6748       emitpcode(POC_ANDLW,popGetLit(0xc0));
6749       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6750       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6751       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6752       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6753       break;
6754     case 7:
6755       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6756       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6757       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6758       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6759       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6760     }
6761   }
6762
6763 }
6764 /*-----------------------------------------------------------------*/
6765 /* shiftR2Left2Result - shift right two bytes from left to result  */
6766 /*-----------------------------------------------------------------*/
6767 static void shiftR2Left2Result (operand *left, int offl,
6768                                 operand *result, int offr,
6769                                 int shCount, int sign)
6770 {
6771   int same=0;
6772
6773   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6774   same = pic14_sameRegs(AOP(result), AOP(left));
6775
6776   if(same && ((offl + MSB16) == offr)){
6777     same=1;
6778     /* don't crash result[offr] */
6779     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6780     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6781   }
6782 /* else {
6783     movLeft2Result(left,offl, result, offr);
6784     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6785   }
6786 */
6787   /* a:x >> shCount (x = lsb(result))*/
6788 /*
6789   if(sign)
6790     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6791   else {
6792     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6793 */
6794   switch(shCount) {
6795   case 0:
6796     break;
6797   case 1:
6798   case 2:
6799   case 3:
6800     if(sign)
6801       emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6802     else
6803       emitCLRC;
6804
6805     if(same) {
6806       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6807       emitpcode(POC_RRF,popGet(AOP(result),offr));
6808     } else {
6809       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6810       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6811       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6812       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6813     }
6814
6815     while(--shCount) {
6816       if(sign)
6817         emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
6818       else
6819         emitCLRC;
6820       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6821       emitpcode(POC_RRF,popGet(AOP(result),offr));
6822     }
6823     break;
6824   case 4:
6825   case 5:
6826     if(same) {
6827
6828       emitpcode(POC_MOVLW, popGetLit(0xf0));
6829       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6830       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6831
6832       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6833       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6834       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6835       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6836     } else {
6837       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6838       emitpcode(POC_ANDLW, popGetLit(0x0f));
6839       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6840
6841       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6842       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6843       emitpcode(POC_ANDLW, popGetLit(0xf0));
6844       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6845       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6846     }
6847
6848     if(shCount >=5) {
6849       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6850       emitpcode(POC_RRF, popGet(AOP(result),offr));
6851     }
6852
6853     if(sign) {
6854       emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
6855       emitpcode(POC_BTFSC, 
6856                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
6857       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6858     }
6859
6860     break;
6861
6862   case 6:
6863     if(same) {
6864
6865       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6866       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6867
6868       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6869       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6870       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6871       emitpcode(POC_ANDLW,popGetLit(0x03));
6872       if(sign) {
6873         emitpcode(POC_BTFSC, 
6874                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
6875         emitpcode(POC_IORLW,popGetLit(0xfc));
6876       }
6877       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6878       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6879       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6880       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6881     } else {
6882       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6883       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6884       emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6885       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6886       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6887       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6888       emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
6889       emitpcode(POC_ANDLW,popGetLit(0x03));
6890       if(sign) {
6891         emitpcode(POC_BTFSC, 
6892                   newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
6893         emitpcode(POC_IORLW,popGetLit(0xfc));
6894       }
6895       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6896       //emitpcode(POC_RLF,  popGet(AOP(result),offr));
6897
6898         
6899     }
6900
6901     break;
6902   case 7:
6903     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6904     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6905     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6906     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6907     if(sign) {
6908       emitSKPNC;
6909       emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
6910     } else 
6911       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6912   }
6913 }
6914
6915
6916 /*-----------------------------------------------------------------*/
6917 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6918 /*-----------------------------------------------------------------*/
6919 static void shiftLLeftOrResult (operand *left, int offl,
6920                                 operand *result, int offr, int shCount)
6921 {
6922     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6923     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6924     /* shift left accumulator */
6925     AccLsh(shCount);
6926     /* or with result */
6927     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6928     /* back to result */
6929     aopPut(AOP(result),"a",offr);
6930 }
6931
6932 /*-----------------------------------------------------------------*/
6933 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6934 /*-----------------------------------------------------------------*/
6935 static void shiftRLeftOrResult (operand *left, int offl,
6936                                 operand *result, int offr, int shCount)
6937 {
6938     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6939     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6940     /* shift right accumulator */
6941     AccRsh(shCount);
6942     /* or with result */
6943     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6944     /* back to result */
6945     aopPut(AOP(result),"a",offr);
6946 }
6947
6948 /*-----------------------------------------------------------------*/
6949 /* genlshOne - left shift a one byte quantity by known count       */
6950 /*-----------------------------------------------------------------*/
6951 static void genlshOne (operand *result, operand *left, int shCount)
6952 {       
6953     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6954     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6955 }
6956
6957 /*-----------------------------------------------------------------*/
6958 /* genlshTwo - left shift two bytes by known amount != 0           */
6959 /*-----------------------------------------------------------------*/
6960 static void genlshTwo (operand *result,operand *left, int shCount)
6961 {
6962     int size;
6963     
6964     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6965     size = pic14_getDataSize(result);
6966
6967     /* if shCount >= 8 */
6968     if (shCount >= 8) {
6969         shCount -= 8 ;
6970
6971         if (size > 1){
6972             if (shCount)
6973                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6974             else 
6975                 movLeft2Result(left, LSB, result, MSB16);
6976         }
6977         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6978     }
6979
6980     /*  1 <= shCount <= 7 */
6981     else {  
6982         if(size == 1)
6983             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6984         else 
6985             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6986     }
6987 }
6988
6989 /*-----------------------------------------------------------------*/
6990 /* shiftLLong - shift left one long from left to result            */
6991 /* offl = LSB or MSB16                                             */
6992 /*-----------------------------------------------------------------*/
6993 static void shiftLLong (operand *left, operand *result, int offr )
6994 {
6995     char *l;
6996     int size = AOP_SIZE(result);
6997
6998     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6999     if(size >= LSB+offr){
7000         l = aopGet(AOP(left),LSB,FALSE,FALSE);
7001         MOVA(l);
7002         pic14_emitcode("add","a,acc");
7003         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7004             size >= MSB16+offr && offr != LSB )
7005             pic14_emitcode("xch","a,%s",
7006                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7007         else        
7008             aopPut(AOP(result),"a",LSB+offr);
7009     }
7010
7011     if(size >= MSB16+offr){
7012         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7013             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7014             MOVA(l);
7015         }
7016         pic14_emitcode("rlc","a");
7017         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7018             size >= MSB24+offr && offr != LSB)
7019             pic14_emitcode("xch","a,%s",
7020                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7021         else        
7022             aopPut(AOP(result),"a",MSB16+offr);
7023     }
7024
7025     if(size >= MSB24+offr){
7026         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7027             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7028             MOVA(l);
7029         }
7030         pic14_emitcode("rlc","a");
7031         if (pic14_sameRegs(AOP(left),AOP(result)) && 
7032             size >= MSB32+offr && offr != LSB )
7033             pic14_emitcode("xch","a,%s",
7034                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7035         else        
7036             aopPut(AOP(result),"a",MSB24+offr);
7037     }
7038
7039     if(size > MSB32+offr){
7040         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7041             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7042             MOVA(l);    
7043         }
7044         pic14_emitcode("rlc","a");
7045         aopPut(AOP(result),"a",MSB32+offr);
7046     }
7047     if(offr != LSB)
7048         aopPut(AOP(result),zero,LSB);       
7049 }
7050
7051 /*-----------------------------------------------------------------*/
7052 /* genlshFour - shift four byte by a known amount != 0             */
7053 /*-----------------------------------------------------------------*/
7054 static void genlshFour (operand *result, operand *left, int shCount)
7055 {
7056     int size;
7057
7058     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7059     size = AOP_SIZE(result);
7060
7061     /* if shifting more that 3 bytes */
7062     if (shCount >= 24 ) {
7063         shCount -= 24;
7064         if (shCount)
7065             /* lowest order of left goes to the highest
7066             order of the destination */
7067             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7068         else
7069             movLeft2Result(left, LSB, result, MSB32);
7070         aopPut(AOP(result),zero,LSB);
7071         aopPut(AOP(result),zero,MSB16);
7072         aopPut(AOP(result),zero,MSB32);
7073         return;
7074     }
7075
7076     /* more than two bytes */
7077     else if ( shCount >= 16 ) {
7078         /* lower order two bytes goes to higher order two bytes */
7079         shCount -= 16;
7080         /* if some more remaining */
7081         if (shCount)
7082             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7083         else {
7084             movLeft2Result(left, MSB16, result, MSB32);
7085             movLeft2Result(left, LSB, result, MSB24);
7086         }
7087         aopPut(AOP(result),zero,MSB16);
7088         aopPut(AOP(result),zero,LSB);
7089         return;
7090     }    
7091
7092     /* if more than 1 byte */
7093     else if ( shCount >= 8 ) {
7094         /* lower order three bytes goes to higher order  three bytes */
7095         shCount -= 8;
7096         if(size == 2){
7097             if(shCount)
7098                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7099             else
7100                 movLeft2Result(left, LSB, result, MSB16);
7101         }
7102         else{   /* size = 4 */
7103             if(shCount == 0){
7104                 movLeft2Result(left, MSB24, result, MSB32);
7105                 movLeft2Result(left, MSB16, result, MSB24);
7106                 movLeft2Result(left, LSB, result, MSB16);
7107                 aopPut(AOP(result),zero,LSB);
7108             }
7109             else if(shCount == 1)
7110                 shiftLLong(left, result, MSB16);
7111             else{
7112                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7113                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7114                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7115                 aopPut(AOP(result),zero,LSB);
7116             }
7117         }
7118     }
7119
7120     /* 1 <= shCount <= 7 */
7121     else if(shCount <= 2){
7122         shiftLLong(left, result, LSB);
7123         if(shCount == 2)
7124             shiftLLong(result, result, LSB);
7125     }
7126     /* 3 <= shCount <= 7, optimize */
7127     else{
7128         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7129         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7130         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7131     }
7132 }
7133
7134 /*-----------------------------------------------------------------*/
7135 /* genLeftShiftLiteral - left shifting by known count              */
7136 /*-----------------------------------------------------------------*/
7137 static void genLeftShiftLiteral (operand *left,
7138                                  operand *right,
7139                                  operand *result,
7140                                  iCode *ic)
7141 {    
7142     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7143     int size;
7144
7145     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7146     freeAsmop(right,NULL,ic,TRUE);
7147
7148     aopOp(left,ic,FALSE);
7149     aopOp(result,ic,FALSE);
7150
7151     size = getSize(operandType(result));
7152
7153 #if VIEW_SIZE
7154     pic14_emitcode("; shift left ","result %d, left %d",size,
7155              AOP_SIZE(left));
7156 #endif
7157
7158     /* I suppose that the left size >= result size */
7159     if(shCount == 0){
7160         while(size--){
7161             movLeft2Result(left, size, result, size);
7162         }
7163     }
7164
7165     else if(shCount >= (size * 8))
7166         while(size--)
7167             aopPut(AOP(result),zero,size);
7168     else{
7169         switch (size) {
7170             case 1:
7171                 genlshOne (result,left,shCount);
7172                 break;
7173
7174             case 2:
7175             case 3:
7176                 genlshTwo (result,left,shCount);
7177                 break;
7178
7179             case 4:
7180                 genlshFour (result,left,shCount);
7181                 break;
7182         }
7183     }
7184     freeAsmop(left,NULL,ic,TRUE);
7185     freeAsmop(result,NULL,ic,TRUE);
7186 }
7187
7188 /*-----------------------------------------------------------------*
7189  * genMultiAsm - repeat assembly instruction for size of register.
7190  * if endian == 1, then the high byte (i.e base address + size of 
7191  * register) is used first else the low byte is used first;
7192  *-----------------------------------------------------------------*/
7193 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7194 {
7195
7196   int offset = 0;
7197
7198   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7199
7200   if(!reg)
7201     return;
7202
7203   if(!endian) {
7204     endian = 1;
7205   } else {
7206     endian = -1;
7207     offset = size-1;
7208   }
7209
7210   while(size--) {
7211     emitpcode(poc,    popGet(AOP(reg),offset));
7212     offset += endian;
7213   }
7214
7215 }
7216 /*-----------------------------------------------------------------*/
7217 /* genLeftShift - generates code for left shifting                 */
7218 /*-----------------------------------------------------------------*/
7219 static void genLeftShift (iCode *ic)
7220 {
7221   operand *left,*right, *result;
7222   int size, offset;
7223   char *l;
7224   symbol *tlbl , *tlbl1;
7225   pCodeOp *pctemp;
7226
7227   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7228
7229   right = IC_RIGHT(ic);
7230   left  = IC_LEFT(ic);
7231   result = IC_RESULT(ic);
7232
7233   aopOp(right,ic,FALSE);
7234
7235   /* if the shift count is known then do it 
7236      as efficiently as possible */
7237   if (AOP_TYPE(right) == AOP_LIT) {
7238     genLeftShiftLiteral (left,right,result,ic);
7239     return ;
7240   }
7241
7242   /* shift count is unknown then we have to form 
7243      a loop get the loop count in B : Note: we take
7244      only the lower order byte since shifting
7245      more that 32 bits make no sense anyway, ( the
7246      largest size of an object can be only 32 bits ) */  
7247
7248     
7249   aopOp(left,ic,FALSE);
7250   aopOp(result,ic,FALSE);
7251
7252   /* now move the left to the result if they are not the
7253      same */
7254   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7255       AOP_SIZE(result) > 1) {
7256
7257     size = AOP_SIZE(result);
7258     offset=0;
7259     while (size--) {
7260       l = aopGet(AOP(left),offset,FALSE,TRUE);
7261       if (*l == '@' && (IS_AOP_PREG(result))) {
7262
7263         pic14_emitcode("mov","a,%s",l);
7264         aopPut(AOP(result),"a",offset);
7265       } else {
7266         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7267         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7268         //aopPut(AOP(result),l,offset);
7269       }
7270       offset++;
7271     }
7272   }
7273
7274   size = AOP_SIZE(result);
7275
7276   /* if it is only one byte then */
7277   if (size == 1) {
7278     if(optimized_for_speed) {
7279       emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7280       emitpcode(POC_ANDLW,  popGetLit(0xf0));
7281       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7282       emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7283       emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7284       emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7285       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7286       emitpcode(POC_RLFW,   popGet(AOP(result),0));
7287       emitpcode(POC_ANDLW,  popGetLit(0xfe));
7288       emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7289       emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7290       emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7291     } else {
7292
7293       tlbl = newiTempLabel(NULL);
7294       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7295         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7296         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7297       }
7298
7299       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7300       emitpcode(POC_RRF,    popGet(AOP(result),0));
7301       emitpLabel(tlbl->key);
7302       emitpcode(POC_RLF,    popGet(AOP(result),0));
7303       emitpcode(POC_ADDLW,  popGetLit(1));
7304       emitSKPC;
7305       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7306     }
7307     goto release ;
7308   }
7309     
7310   if (pic14_sameRegs(AOP(left),AOP(result))) {
7311
7312     tlbl = newiTempLabel(NULL);
7313     emitpcode(POC_COMFW,  popGet(AOP(right),0));
7314     genMultiAsm(POC_RRF, result, size,1);
7315     emitpLabel(tlbl->key);
7316     genMultiAsm(POC_RLF, result, size,0);
7317     emitpcode(POC_ADDLW,  popGetLit(1));
7318     emitSKPC;
7319     emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7320     goto release;
7321   }
7322
7323   //tlbl = newiTempLabel(NULL);
7324   //offset = 0 ;   
7325   //tlbl1 = newiTempLabel(NULL);
7326
7327   //reAdjustPreg(AOP(result));    
7328     
7329   //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7330   //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7331   //l = aopGet(AOP(result),offset,FALSE,FALSE);
7332   //MOVA(l);
7333   //pic14_emitcode("add","a,acc");         
7334   //aopPut(AOP(result),"a",offset++);
7335   //while (--size) {
7336   //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7337   //  MOVA(l);
7338   //  pic14_emitcode("rlc","a");         
7339   //  aopPut(AOP(result),"a",offset++);
7340   //}
7341   //reAdjustPreg(AOP(result));
7342
7343   //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7344   //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7345
7346
7347   tlbl = newiTempLabel(NULL);
7348   tlbl1= newiTempLabel(NULL);
7349
7350   size = AOP_SIZE(result);
7351   offset = 1;
7352
7353   pctemp = popGetTempReg();  /* grab a temporary working register. */
7354
7355   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7356
7357   /* offset should be 0, 1 or 3 */
7358   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7359   emitSKPNZ;
7360   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7361
7362   emitpcode(POC_MOVWF, pctemp);
7363
7364
7365   emitpLabel(tlbl->key);
7366
7367   emitCLRC;
7368   emitpcode(POC_RLF,  popGet(AOP(result),0));
7369   while(--size)
7370     emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7371
7372   emitpcode(POC_DECFSZ,  pctemp);
7373   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7374   emitpLabel(tlbl1->key);
7375
7376   popReleaseTempReg(pctemp);
7377
7378
7379  release:
7380   freeAsmop (right,NULL,ic,TRUE);
7381   freeAsmop(left,NULL,ic,TRUE);
7382   freeAsmop(result,NULL,ic,TRUE);
7383 }
7384
7385 /*-----------------------------------------------------------------*/
7386 /* genrshOne - right shift a one byte quantity by known count      */
7387 /*-----------------------------------------------------------------*/
7388 static void genrshOne (operand *result, operand *left,
7389                        int shCount, int sign)
7390 {
7391     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7392     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7393 }
7394
7395 /*-----------------------------------------------------------------*/
7396 /* genrshTwo - right shift two bytes by known amount != 0          */
7397 /*-----------------------------------------------------------------*/
7398 static void genrshTwo (operand *result,operand *left,
7399                        int shCount, int sign)
7400 {
7401   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7402   /* if shCount >= 8 */
7403   if (shCount >= 8) {
7404     shCount -= 8 ;
7405     if (shCount)
7406       shiftR1Left2Result(left, MSB16, result, LSB,
7407                          shCount, sign);
7408     else
7409       movLeft2Result(left, MSB16, result, LSB);
7410
7411     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7412
7413     if(sign) {
7414       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7415       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7416     }
7417   }
7418
7419   /*  1 <= shCount <= 7 */
7420   else
7421     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7422 }
7423
7424 /*-----------------------------------------------------------------*/
7425 /* shiftRLong - shift right one long from left to result           */
7426 /* offl = LSB or MSB16                                             */
7427 /*-----------------------------------------------------------------*/
7428 static void shiftRLong (operand *left, int offl,
7429                         operand *result, int sign)
7430 {
7431     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7432     if(!sign)
7433         pic14_emitcode("clr","c");
7434     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7435     if(sign)
7436         pic14_emitcode("mov","c,acc.7");
7437     pic14_emitcode("rrc","a");
7438     aopPut(AOP(result),"a",MSB32-offl);
7439     if(offl == MSB16)
7440         /* add sign of "a" */
7441         addSign(result, MSB32, sign);
7442
7443     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7444     pic14_emitcode("rrc","a");
7445     aopPut(AOP(result),"a",MSB24-offl);
7446
7447     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7448     pic14_emitcode("rrc","a");
7449     aopPut(AOP(result),"a",MSB16-offl);
7450
7451     if(offl == LSB){
7452         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7453         pic14_emitcode("rrc","a");
7454         aopPut(AOP(result),"a",LSB);
7455     }
7456 }
7457
7458 /*-----------------------------------------------------------------*/
7459 /* genrshFour - shift four byte by a known amount != 0             */
7460 /*-----------------------------------------------------------------*/
7461 static void genrshFour (operand *result, operand *left,
7462                         int shCount, int sign)
7463 {
7464   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7465   /* if shifting more that 3 bytes */
7466   if(shCount >= 24 ) {
7467     shCount -= 24;
7468     if(shCount)
7469       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7470     else
7471       movLeft2Result(left, MSB32, result, LSB);
7472
7473     addSign(result, MSB16, sign);
7474   }
7475   else if(shCount >= 16){
7476     shCount -= 16;
7477     if(shCount)
7478       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7479     else{
7480       movLeft2Result(left, MSB24, result, LSB);
7481       movLeft2Result(left, MSB32, result, MSB16);
7482     }
7483     addSign(result, MSB24, sign);
7484   }
7485   else if(shCount >= 8){
7486     shCount -= 8;
7487     if(shCount == 1)
7488       shiftRLong(left, MSB16, result, sign);
7489     else if(shCount == 0){
7490       movLeft2Result(left, MSB16, result, LSB);
7491       movLeft2Result(left, MSB24, result, MSB16);
7492       movLeft2Result(left, MSB32, result, MSB24);
7493       addSign(result, MSB32, sign);
7494     }
7495     else{
7496       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7497       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7498       /* the last shift is signed */
7499       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7500       addSign(result, MSB32, sign);
7501     }
7502   }
7503   else{   /* 1 <= shCount <= 7 */
7504     if(shCount <= 2){
7505       shiftRLong(left, LSB, result, sign);
7506       if(shCount == 2)
7507         shiftRLong(result, LSB, result, sign);
7508     }
7509     else{
7510       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7511       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7512       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7513     }
7514   }
7515 }
7516
7517 /*-----------------------------------------------------------------*/
7518 /* genRightShiftLiteral - right shifting by known count            */
7519 /*-----------------------------------------------------------------*/
7520 static void genRightShiftLiteral (operand *left,
7521                                   operand *right,
7522                                   operand *result,
7523                                   iCode *ic,
7524                                   int sign)
7525 {    
7526   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7527   int lsize,res_size;
7528
7529   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7530   freeAsmop(right,NULL,ic,TRUE);
7531
7532   aopOp(left,ic,FALSE);
7533   aopOp(result,ic,FALSE);
7534
7535 #if VIEW_SIZE
7536   pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7537                  AOP_SIZE(left));
7538 #endif
7539
7540   lsize = pic14_getDataSize(left);
7541   res_size = pic14_getDataSize(result);
7542   /* test the LEFT size !!! */
7543
7544   /* I suppose that the left size >= result size */
7545   if(shCount == 0){
7546     while(res_size--)
7547       movLeft2Result(left, lsize, result, res_size);
7548   }
7549
7550   else if(shCount >= (lsize * 8)){
7551
7552     if(res_size == 1) {
7553       emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7554       if(sign) {
7555         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7556         emitpcode(POC_DECF, popGet(AOP(result),LSB));
7557       }
7558     } else {
7559
7560       if(sign) {
7561         emitpcode(POC_MOVLW, popGetLit(0));
7562         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7563         emitpcode(POC_MOVLW, popGetLit(0xff));
7564         while(res_size--)
7565           emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7566
7567       } else {
7568
7569         while(res_size--)
7570           emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7571       }
7572     }
7573   } else {
7574
7575     switch (res_size) {
7576     case 1:
7577       genrshOne (result,left,shCount,sign);
7578       break;
7579
7580     case 2:
7581       genrshTwo (result,left,shCount,sign);
7582       break;
7583
7584     case 4:
7585       genrshFour (result,left,shCount,sign);
7586       break;
7587     default :
7588       break;
7589     }
7590
7591   }
7592
7593   freeAsmop(left,NULL,ic,TRUE);
7594   freeAsmop(result,NULL,ic,TRUE);
7595 }
7596
7597 /*-----------------------------------------------------------------*/
7598 /* genSignedRightShift - right shift of signed number              */
7599 /*-----------------------------------------------------------------*/
7600 static void genSignedRightShift (iCode *ic)
7601 {
7602   operand *right, *left, *result;
7603   int size, offset;
7604   //  char *l;
7605   symbol *tlbl, *tlbl1 ;
7606   pCodeOp *pctemp;
7607
7608   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7609
7610   /* we do it the hard way put the shift count in b
7611      and loop thru preserving the sign */
7612   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7613
7614   right = IC_RIGHT(ic);
7615   left  = IC_LEFT(ic);
7616   result = IC_RESULT(ic);
7617
7618   aopOp(right,ic,FALSE);  
7619   aopOp(left,ic,FALSE);
7620   aopOp(result,ic,FALSE);
7621
7622
7623   if ( AOP_TYPE(right) == AOP_LIT) {
7624     genRightShiftLiteral (left,right,result,ic,1);
7625     return ;
7626   }
7627   /* shift count is unknown then we have to form 
7628      a loop get the loop count in B : Note: we take
7629      only the lower order byte since shifting
7630      more that 32 bits make no sense anyway, ( the
7631      largest size of an object can be only 32 bits ) */  
7632
7633   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7634   //pic14_emitcode("inc","b");
7635   //freeAsmop (right,NULL,ic,TRUE);
7636   //aopOp(left,ic,FALSE);
7637   //aopOp(result,ic,FALSE);
7638
7639   /* now move the left to the result if they are not the
7640      same */
7641   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7642       AOP_SIZE(result) > 1) {
7643
7644     size = AOP_SIZE(result);
7645     offset=0;
7646     while (size--) { 
7647       /*
7648         l = aopGet(AOP(left),offset,FALSE,TRUE);
7649         if (*l == '@' && IS_AOP_PREG(result)) {
7650
7651         pic14_emitcode("mov","a,%s",l);
7652         aopPut(AOP(result),"a",offset);
7653         } else
7654         aopPut(AOP(result),l,offset);
7655       */
7656       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7657       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7658
7659       offset++;
7660     }
7661   }
7662
7663   /* mov the highest order bit to OVR */    
7664   tlbl = newiTempLabel(NULL);
7665   tlbl1= newiTempLabel(NULL);
7666
7667   size = AOP_SIZE(result);
7668   offset = size - 1;
7669
7670   pctemp = popGetTempReg();  /* grab a temporary working register. */
7671
7672   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7673
7674   /* offset should be 0, 1 or 3 */
7675   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7676   emitSKPNZ;
7677   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7678
7679   emitpcode(POC_MOVWF, pctemp);
7680
7681
7682   emitpLabel(tlbl->key);
7683
7684   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7685   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7686
7687   while(--size) {
7688     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7689   }
7690
7691   emitpcode(POC_DECFSZ,  pctemp);
7692   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7693   emitpLabel(tlbl1->key);
7694
7695   popReleaseTempReg(pctemp);
7696 #if 0
7697   size = AOP_SIZE(result);
7698   offset = size - 1;
7699   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7700   pic14_emitcode("rlc","a");
7701   pic14_emitcode("mov","ov,c");
7702   /* if it is only one byte then */
7703   if (size == 1) {
7704     l = aopGet(AOP(left),0,FALSE,FALSE);
7705     MOVA(l);
7706     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7707     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7708     pic14_emitcode("mov","c,ov");
7709     pic14_emitcode("rrc","a");
7710     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7711     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7712     aopPut(AOP(result),"a",0);
7713     goto release ;
7714   }
7715
7716   reAdjustPreg(AOP(result));
7717   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7718   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7719   pic14_emitcode("mov","c,ov");
7720   while (size--) {
7721     l = aopGet(AOP(result),offset,FALSE,FALSE);
7722     MOVA(l);
7723     pic14_emitcode("rrc","a");         
7724     aopPut(AOP(result),"a",offset--);
7725   }
7726   reAdjustPreg(AOP(result));
7727   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7728   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7729
7730  release:
7731 #endif
7732
7733   freeAsmop(left,NULL,ic,TRUE);
7734   freeAsmop(result,NULL,ic,TRUE);
7735   freeAsmop(right,NULL,ic,TRUE);
7736 }
7737
7738 /*-----------------------------------------------------------------*/
7739 /* genRightShift - generate code for right shifting                */
7740 /*-----------------------------------------------------------------*/
7741 static void genRightShift (iCode *ic)
7742 {
7743     operand *right, *left, *result;
7744     sym_link *retype ;
7745     int size, offset;
7746     char *l;
7747     symbol *tlbl, *tlbl1 ;
7748
7749     /* if signed then we do it the hard way preserve the
7750     sign bit moving it inwards */
7751     retype = getSpec(operandType(IC_RESULT(ic)));
7752     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7753
7754     if (!SPEC_USIGN(retype)) {
7755         genSignedRightShift (ic);
7756         return ;
7757     }
7758
7759     /* signed & unsigned types are treated the same : i.e. the
7760     signed is NOT propagated inwards : quoting from the
7761     ANSI - standard : "for E1 >> E2, is equivalent to division
7762     by 2**E2 if unsigned or if it has a non-negative value,
7763     otherwise the result is implementation defined ", MY definition
7764     is that the sign does not get propagated */
7765
7766     right = IC_RIGHT(ic);
7767     left  = IC_LEFT(ic);
7768     result = IC_RESULT(ic);
7769
7770     aopOp(right,ic,FALSE);
7771
7772     /* if the shift count is known then do it 
7773     as efficiently as possible */
7774     if (AOP_TYPE(right) == AOP_LIT) {
7775         genRightShiftLiteral (left,right,result,ic, 0);
7776         return ;
7777     }
7778
7779     /* shift count is unknown then we have to form 
7780     a loop get the loop count in B : Note: we take
7781     only the lower order byte since shifting
7782     more that 32 bits make no sense anyway, ( the
7783     largest size of an object can be only 32 bits ) */  
7784
7785     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7786     pic14_emitcode("inc","b");
7787     aopOp(left,ic,FALSE);
7788     aopOp(result,ic,FALSE);
7789
7790     /* now move the left to the result if they are not the
7791     same */
7792     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7793         AOP_SIZE(result) > 1) {
7794
7795         size = AOP_SIZE(result);
7796         offset=0;
7797         while (size--) {
7798             l = aopGet(AOP(left),offset,FALSE,TRUE);
7799             if (*l == '@' && IS_AOP_PREG(result)) {
7800
7801                 pic14_emitcode("mov","a,%s",l);
7802                 aopPut(AOP(result),"a",offset);
7803             } else
7804                 aopPut(AOP(result),l,offset);
7805             offset++;
7806         }
7807     }
7808
7809     tlbl = newiTempLabel(NULL);
7810     tlbl1= newiTempLabel(NULL);
7811     size = AOP_SIZE(result);
7812     offset = size - 1;
7813
7814     /* if it is only one byte then */
7815     if (size == 1) {
7816
7817       tlbl = newiTempLabel(NULL);
7818       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7819         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7820         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7821       }
7822
7823       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7824       emitpcode(POC_RLF,    popGet(AOP(result),0));
7825       emitpLabel(tlbl->key);
7826       emitpcode(POC_RRF,    popGet(AOP(result),0));
7827       emitpcode(POC_ADDLW,  popGetLit(1));
7828       emitSKPC;
7829       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7830
7831       goto release ;
7832     }
7833
7834     reAdjustPreg(AOP(result));
7835     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7836     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7837     CLRC;
7838     while (size--) {
7839         l = aopGet(AOP(result),offset,FALSE,FALSE);
7840         MOVA(l);
7841         pic14_emitcode("rrc","a");         
7842         aopPut(AOP(result),"a",offset--);
7843     }
7844     reAdjustPreg(AOP(result));
7845
7846     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7847     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7848
7849 release:
7850     freeAsmop(left,NULL,ic,TRUE);
7851     freeAsmop (right,NULL,ic,TRUE);
7852     freeAsmop(result,NULL,ic,TRUE);
7853 }
7854
7855 /*-----------------------------------------------------------------*/
7856 /* genUnpackBits - generates code for unpacking bits               */
7857 /*-----------------------------------------------------------------*/
7858 static void genUnpackBits (operand *result, char *rname, int ptype)
7859 {    
7860     int shCnt ;
7861     int rlen = 0 ;
7862     sym_link *etype;
7863     int offset = 0 ;
7864
7865     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7866     etype = getSpec(operandType(result));
7867
7868     /* read the first byte  */
7869     switch (ptype) {
7870
7871     case POINTER:
7872     case IPOINTER:
7873         pic14_emitcode("mov","a,@%s",rname);
7874         break;
7875         
7876     case PPOINTER:
7877         pic14_emitcode("movx","a,@%s",rname);
7878         break;
7879         
7880     case FPOINTER:
7881         pic14_emitcode("movx","a,@dptr");
7882         break;
7883
7884     case CPOINTER:
7885         pic14_emitcode("clr","a");
7886         pic14_emitcode("movc","a","@a+dptr");
7887         break;
7888
7889     case GPOINTER:
7890         pic14_emitcode("lcall","__gptrget");
7891         break;
7892     }
7893
7894     /* if we have bitdisplacement then it fits   */
7895     /* into this byte completely or if length is */
7896     /* less than a byte                          */
7897     if ((shCnt = SPEC_BSTR(etype)) || 
7898         (SPEC_BLEN(etype) <= 8))  {
7899
7900         /* shift right acc */
7901         AccRsh(shCnt);
7902
7903         pic14_emitcode("anl","a,#0x%02x",
7904                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7905         aopPut(AOP(result),"a",offset);
7906         return ;
7907     }
7908
7909     /* bit field did not fit in a byte  */
7910     rlen = SPEC_BLEN(etype) - 8;
7911     aopPut(AOP(result),"a",offset++);
7912
7913     while (1)  {
7914
7915         switch (ptype) {
7916         case POINTER:
7917         case IPOINTER:
7918             pic14_emitcode("inc","%s",rname);
7919             pic14_emitcode("mov","a,@%s",rname);
7920             break;
7921             
7922         case PPOINTER:
7923             pic14_emitcode("inc","%s",rname);
7924             pic14_emitcode("movx","a,@%s",rname);
7925             break;
7926
7927         case FPOINTER:
7928             pic14_emitcode("inc","dptr");
7929             pic14_emitcode("movx","a,@dptr");
7930             break;
7931             
7932         case CPOINTER:
7933             pic14_emitcode("clr","a");
7934             pic14_emitcode("inc","dptr");
7935             pic14_emitcode("movc","a","@a+dptr");
7936             break;
7937             
7938         case GPOINTER:
7939             pic14_emitcode("inc","dptr");
7940             pic14_emitcode("lcall","__gptrget");
7941             break;
7942         }
7943
7944         rlen -= 8;            
7945         /* if we are done */
7946         if ( rlen <= 0 )
7947             break ;
7948         
7949         aopPut(AOP(result),"a",offset++);
7950                               
7951     }
7952     
7953     if (rlen) {
7954         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7955         aopPut(AOP(result),"a",offset);        
7956     }
7957     
7958     return ;
7959 }
7960
7961 #if 0
7962 /*-----------------------------------------------------------------*/
7963 /* genDataPointerGet - generates code when ptr offset is known     */
7964 /*-----------------------------------------------------------------*/
7965 static void genDataPointerGet (operand *left, 
7966                                operand *result, 
7967                                iCode *ic)
7968 {
7969   int size , offset = 0;
7970
7971
7972   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7973
7974
7975   /* optimization - most of the time, left and result are the same
7976    * address, but different types. for the pic code, we could omit
7977    * the following
7978    */
7979
7980   aopOp(result,ic,TRUE);
7981
7982   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7983
7984   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7985
7986   size = AOP_SIZE(result);
7987
7988   while (size--) {
7989     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7990     offset++;
7991   }
7992
7993   freeAsmop(left,NULL,ic,TRUE);
7994   freeAsmop(result,NULL,ic,TRUE);
7995 }
7996 #endif
7997 /*-----------------------------------------------------------------*/
7998 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7999 /*-----------------------------------------------------------------*/
8000 static void genNearPointerGet (operand *left, 
8001                                operand *result, 
8002                                iCode *ic)
8003 {
8004     asmop *aop = NULL;
8005     //regs *preg = NULL ;
8006     char *rname ;
8007     sym_link *rtype, *retype;
8008     sym_link *ltype = operandType(left);    
8009     //char buffer[80];
8010
8011     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8012
8013     rtype = operandType(result);
8014     retype= getSpec(rtype);
8015     
8016     aopOp(left,ic,FALSE);
8017     
8018     /* if left is rematerialisable and
8019        result is not bit variable type and
8020        the left is pointer to data space i.e
8021        lower 128 bytes of space */
8022     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8023         !IS_BITVAR(retype)         &&
8024         DCL_TYPE(ltype) == POINTER) {
8025       //genDataPointerGet (left,result,ic);
8026         return ;
8027     }
8028     
8029     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8030
8031         /* if the value is already in a pointer register
8032        then don't need anything more */
8033     if (!AOP_INPREG(AOP(left))) {
8034         /* otherwise get a free pointer register */
8035     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8036 /*
8037         aop = newAsmop(0);
8038         preg = getFreePtr(ic,&aop,FALSE);
8039         pic14_emitcode("mov","%s,%s",
8040                 preg->name,
8041                 aopGet(AOP(left),0,FALSE,TRUE));
8042         rname = preg->name ;
8043 */
8044     rname ="BAD";
8045     } else
8046         rname = aopGet(AOP(left),0,FALSE,FALSE);
8047     
8048     aopOp (result,ic,FALSE);
8049     
8050       /* if bitfield then unpack the bits */
8051     if (IS_BITVAR(retype)) 
8052         genUnpackBits (result,rname,POINTER);
8053     else {
8054         /* we have can just get the values */
8055       int size = AOP_SIZE(result);
8056       int offset = 0 ;  
8057         
8058       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8059
8060       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8061       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8062       while(size--) {
8063         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8064         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8065         if(size)
8066           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8067       }
8068 /*
8069         while (size--) {
8070             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8071
8072                 pic14_emitcode("mov","a,@%s",rname);
8073                 aopPut(AOP(result),"a",offset);
8074             } else {
8075                 sprintf(buffer,"@%s",rname);
8076                 aopPut(AOP(result),buffer,offset);
8077             }
8078             offset++ ;
8079             if (size)
8080                 pic14_emitcode("inc","%s",rname);
8081         }
8082 */
8083     }
8084
8085     /* now some housekeeping stuff */
8086     if (aop) {
8087         /* we had to allocate for this iCode */
8088     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8089         freeAsmop(NULL,aop,ic,TRUE);
8090     } else { 
8091         /* we did not allocate which means left
8092            already in a pointer register, then
8093            if size > 0 && this could be used again
8094            we have to point it back to where it 
8095            belongs */
8096     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8097         if (AOP_SIZE(result) > 1 &&
8098             !OP_SYMBOL(left)->remat &&
8099             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8100               ic->depth )) {
8101             int size = AOP_SIZE(result) - 1;
8102             while (size--)
8103                 pic14_emitcode("dec","%s",rname);
8104         }
8105     }
8106
8107     /* done */
8108     freeAsmop(left,NULL,ic,TRUE);
8109     freeAsmop(result,NULL,ic,TRUE);
8110      
8111 }
8112
8113 /*-----------------------------------------------------------------*/
8114 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8115 /*-----------------------------------------------------------------*/
8116 static void genPagedPointerGet (operand *left, 
8117                                operand *result, 
8118                                iCode *ic)
8119 {
8120     asmop *aop = NULL;
8121     regs *preg = NULL ;
8122     char *rname ;
8123     sym_link *rtype, *retype;    
8124
8125     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8126
8127     rtype = operandType(result);
8128     retype= getSpec(rtype);
8129     
8130     aopOp(left,ic,FALSE);
8131
8132   /* if the value is already in a pointer register
8133        then don't need anything more */
8134     if (!AOP_INPREG(AOP(left))) {
8135         /* otherwise get a free pointer register */
8136         aop = newAsmop(0);
8137         preg = getFreePtr(ic,&aop,FALSE);
8138         pic14_emitcode("mov","%s,%s",
8139                 preg->name,
8140                 aopGet(AOP(left),0,FALSE,TRUE));
8141         rname = preg->name ;
8142     } else
8143         rname = aopGet(AOP(left),0,FALSE,FALSE);
8144     
8145     freeAsmop(left,NULL,ic,TRUE);
8146     aopOp (result,ic,FALSE);
8147
8148     /* if bitfield then unpack the bits */
8149     if (IS_BITVAR(retype)) 
8150         genUnpackBits (result,rname,PPOINTER);
8151     else {
8152         /* we have can just get the values */
8153         int size = AOP_SIZE(result);
8154         int offset = 0 ;        
8155         
8156         while (size--) {
8157             
8158             pic14_emitcode("movx","a,@%s",rname);
8159             aopPut(AOP(result),"a",offset);
8160             
8161             offset++ ;
8162             
8163             if (size)
8164                 pic14_emitcode("inc","%s",rname);
8165         }
8166     }
8167
8168     /* now some housekeeping stuff */
8169     if (aop) {
8170         /* we had to allocate for this iCode */
8171         freeAsmop(NULL,aop,ic,TRUE);
8172     } else { 
8173         /* we did not allocate which means left
8174            already in a pointer register, then
8175            if size > 0 && this could be used again
8176            we have to point it back to where it 
8177            belongs */
8178         if (AOP_SIZE(result) > 1 &&
8179             !OP_SYMBOL(left)->remat &&
8180             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8181               ic->depth )) {
8182             int size = AOP_SIZE(result) - 1;
8183             while (size--)
8184                 pic14_emitcode("dec","%s",rname);
8185         }
8186     }
8187
8188     /* done */
8189     freeAsmop(result,NULL,ic,TRUE);
8190     
8191         
8192 }
8193
8194 /*-----------------------------------------------------------------*/
8195 /* genFarPointerGet - gget value from far space                    */
8196 /*-----------------------------------------------------------------*/
8197 static void genFarPointerGet (operand *left,
8198                               operand *result, iCode *ic)
8199 {
8200     int size, offset ;
8201     sym_link *retype = getSpec(operandType(result));
8202
8203     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8204
8205     aopOp(left,ic,FALSE);
8206
8207     /* if the operand is already in dptr 
8208     then we do nothing else we move the value to dptr */
8209     if (AOP_TYPE(left) != AOP_STR) {
8210         /* if this is remateriazable */
8211         if (AOP_TYPE(left) == AOP_IMMD)
8212             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8213         else { /* we need to get it byte by byte */
8214             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8215             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8216             if (options.model == MODEL_FLAT24)
8217             {
8218                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8219             }
8220         }
8221     }
8222     /* so dptr know contains the address */
8223     freeAsmop(left,NULL,ic,TRUE);
8224     aopOp(result,ic,FALSE);
8225
8226     /* if bit then unpack */
8227     if (IS_BITVAR(retype)) 
8228         genUnpackBits(result,"dptr",FPOINTER);
8229     else {
8230         size = AOP_SIZE(result);
8231         offset = 0 ;
8232
8233         while (size--) {
8234             pic14_emitcode("movx","a,@dptr");
8235             aopPut(AOP(result),"a",offset++);
8236             if (size)
8237                 pic14_emitcode("inc","dptr");
8238         }
8239     }
8240
8241     freeAsmop(result,NULL,ic,TRUE);
8242 }
8243 #if 0
8244 /*-----------------------------------------------------------------*/
8245 /* genCodePointerGet - get value from code space                  */
8246 /*-----------------------------------------------------------------*/
8247 static void genCodePointerGet (operand *left,
8248                                 operand *result, iCode *ic)
8249 {
8250     int size, offset ;
8251     sym_link *retype = getSpec(operandType(result));
8252
8253     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8254
8255     aopOp(left,ic,FALSE);
8256
8257     /* if the operand is already in dptr 
8258     then we do nothing else we move the value to dptr */
8259     if (AOP_TYPE(left) != AOP_STR) {
8260         /* if this is remateriazable */
8261         if (AOP_TYPE(left) == AOP_IMMD)
8262             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8263         else { /* we need to get it byte by byte */
8264             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8265             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8266             if (options.model == MODEL_FLAT24)
8267             {
8268                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8269             }
8270         }
8271     }
8272     /* so dptr know contains the address */
8273     freeAsmop(left,NULL,ic,TRUE);
8274     aopOp(result,ic,FALSE);
8275
8276     /* if bit then unpack */
8277     if (IS_BITVAR(retype)) 
8278         genUnpackBits(result,"dptr",CPOINTER);
8279     else {
8280         size = AOP_SIZE(result);
8281         offset = 0 ;
8282
8283         while (size--) {
8284             pic14_emitcode("clr","a");
8285             pic14_emitcode("movc","a,@a+dptr");
8286             aopPut(AOP(result),"a",offset++);
8287             if (size)
8288                 pic14_emitcode("inc","dptr");
8289         }
8290     }
8291
8292     freeAsmop(result,NULL,ic,TRUE);
8293 }
8294 #endif
8295 /*-----------------------------------------------------------------*/
8296 /* genGenPointerGet - gget value from generic pointer space        */
8297 /*-----------------------------------------------------------------*/
8298 static void genGenPointerGet (operand *left,
8299                               operand *result, iCode *ic)
8300 {
8301   int size, offset ;
8302   sym_link *retype = getSpec(operandType(result));
8303
8304   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8305   aopOp(left,ic,FALSE);
8306   aopOp(result,ic,FALSE);
8307
8308
8309   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8310
8311   /* if the operand is already in dptr 
8312      then we do nothing else we move the value to dptr */
8313   //  if (AOP_TYPE(left) != AOP_STR) {
8314     /* if this is remateriazable */
8315     if (AOP_TYPE(left) == AOP_IMMD) {
8316       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8317       pic14_emitcode("mov","b,#%d",pointerCode(retype));
8318     }
8319     else { /* we need to get it byte by byte */
8320
8321       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8322       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8323
8324       size = AOP_SIZE(result);
8325       offset = 0 ;
8326
8327       while(size--) {
8328         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8329         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8330         if(size)
8331           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8332       }
8333       goto release;
8334     }
8335     //}
8336   /* so dptr know contains the address */
8337
8338   /* if bit then unpack */
8339   //if (IS_BITVAR(retype)) 
8340   //  genUnpackBits(result,"dptr",GPOINTER);
8341
8342  release:
8343   freeAsmop(left,NULL,ic,TRUE);
8344   freeAsmop(result,NULL,ic,TRUE);
8345
8346 }
8347
8348 /*-----------------------------------------------------------------*/
8349 /* genConstPointerGet - get value from const generic pointer space */
8350 /*-----------------------------------------------------------------*/
8351 static void genConstPointerGet (operand *left,
8352                                 operand *result, iCode *ic)
8353 {
8354   //sym_link *retype = getSpec(operandType(result));
8355   symbol *albl = newiTempLabel(NULL);
8356   symbol *blbl = newiTempLabel(NULL);
8357   PIC_OPCODE poc;
8358
8359   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8360   aopOp(left,ic,FALSE);
8361   aopOp(result,ic,FALSE);
8362
8363
8364   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8365
8366   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8367
8368   emitpcode(POC_CALL,popGetLabel(albl->key));
8369   emitpcodePagesel(popGetLabel(blbl->key)->name); /* Must restore PCLATH before goto, without destroying W */
8370   emitpcode(POC_GOTO,popGetLabel(blbl->key));
8371   emitpLabel(albl->key);
8372
8373   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8374     
8375   emitpcode(poc,popGet(AOP(left),1));
8376   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8377   emitpcode(poc,popGet(AOP(left),0));
8378   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8379
8380   emitpLabel(blbl->key);
8381
8382   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8383
8384
8385   freeAsmop(left,NULL,ic,TRUE);
8386   freeAsmop(result,NULL,ic,TRUE);
8387
8388 }
8389 /*-----------------------------------------------------------------*/
8390 /* genPointerGet - generate code for pointer get                   */
8391 /*-----------------------------------------------------------------*/
8392 static void genPointerGet (iCode *ic)
8393 {
8394     operand *left, *result ;
8395     sym_link *type, *etype;
8396     int p_type;
8397
8398     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8399
8400     left = IC_LEFT(ic);
8401     result = IC_RESULT(ic) ;
8402
8403     /* depending on the type of pointer we need to
8404     move it to the correct pointer register */
8405     type = operandType(left);
8406     etype = getSpec(type);
8407
8408 #if 0
8409     if (IS_PTR_CONST(type))
8410 #else
8411     if (IS_CODEPTR(type))
8412 #endif
8413       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8414
8415     /* if left is of type of pointer then it is simple */
8416     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8417         p_type = DCL_TYPE(type);
8418     else {
8419         /* we have to go by the storage class */
8420         p_type = PTR_TYPE(SPEC_OCLS(etype));
8421
8422         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8423
8424         if (SPEC_OCLS(etype)->codesp ) {
8425           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8426           //p_type = CPOINTER ; 
8427         }
8428         else
8429             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8430               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8431                /*p_type = FPOINTER ;*/ 
8432             else
8433                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8434                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8435 /*                  p_type = PPOINTER; */
8436                 else
8437                     if (SPEC_OCLS(etype) == idata )
8438                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8439 /*                      p_type = IPOINTER; */
8440                     else
8441                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8442 /*                      p_type = POINTER ; */
8443     }
8444
8445     /* now that we have the pointer type we assign
8446     the pointer values */
8447     switch (p_type) {
8448
8449     case POINTER:       
8450     case IPOINTER:
8451         genNearPointerGet (left,result,ic);
8452         break;
8453
8454     case PPOINTER:
8455         genPagedPointerGet(left,result,ic);
8456         break;
8457
8458     case FPOINTER:
8459         genFarPointerGet (left,result,ic);
8460         break;
8461
8462     case CPOINTER:
8463         genConstPointerGet (left,result,ic);
8464         //pic14_emitcodePointerGet (left,result,ic);
8465         break;
8466
8467     case GPOINTER:
8468 #if 0
8469       if (IS_PTR_CONST(type))
8470         genConstPointerGet (left,result,ic);
8471       else
8472 #endif
8473         genGenPointerGet (left,result,ic);
8474       break;
8475     }
8476
8477 }
8478
8479 /*-----------------------------------------------------------------*/
8480 /* genPackBits - generates code for packed bit storage             */
8481 /*-----------------------------------------------------------------*/
8482 static void genPackBits (sym_link    *etype ,
8483                          operand *right ,
8484                          char *rname, int p_type)
8485 {
8486     int shCount = 0 ;
8487     int offset = 0  ;
8488     int rLen = 0 ;
8489     int blen, bstr ;   
8490     char *l ;
8491
8492     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8493     blen = SPEC_BLEN(etype);
8494     bstr = SPEC_BSTR(etype);
8495
8496     l = aopGet(AOP(right),offset++,FALSE,FALSE);
8497     MOVA(l);   
8498
8499     /* if the bit lenth is less than or    */
8500     /* it exactly fits a byte then         */
8501     if (SPEC_BLEN(etype) <= 8 )  {
8502         shCount = SPEC_BSTR(etype) ;
8503
8504         /* shift left acc */
8505         AccLsh(shCount);
8506
8507         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8508
8509
8510             switch (p_type) {
8511                 case POINTER:
8512                     pic14_emitcode ("mov","b,a");
8513                     pic14_emitcode("mov","a,@%s",rname);
8514                     break;
8515
8516                 case FPOINTER:
8517                     pic14_emitcode ("mov","b,a");
8518                     pic14_emitcode("movx","a,@dptr");
8519                     break;
8520
8521                 case GPOINTER:
8522                     pic14_emitcode ("push","b");
8523                     pic14_emitcode ("push","acc");
8524                     pic14_emitcode ("lcall","__gptrget");
8525                     pic14_emitcode ("pop","b");
8526                     break;
8527             }
8528
8529             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8530                       ((unsigned char)(0xFF << (blen+bstr)) | 
8531                        (unsigned char)(0xFF >> (8-bstr)) ) );
8532             pic14_emitcode ("orl","a,b");
8533             if (p_type == GPOINTER)
8534                 pic14_emitcode("pop","b");
8535         }
8536     }
8537
8538     switch (p_type) {
8539         case POINTER:
8540             pic14_emitcode("mov","@%s,a",rname);
8541             break;
8542
8543         case FPOINTER:
8544             pic14_emitcode("movx","@dptr,a");
8545             break;
8546
8547         case GPOINTER:
8548             DEBUGpic14_emitcode(";lcall","__gptrput");
8549             break;
8550     }
8551
8552     /* if we r done */
8553     if ( SPEC_BLEN(etype) <= 8 )
8554         return ;
8555
8556     pic14_emitcode("inc","%s",rname);
8557     rLen = SPEC_BLEN(etype) ;     
8558
8559     /* now generate for lengths greater than one byte */
8560     while (1) {
8561
8562         l = aopGet(AOP(right),offset++,FALSE,TRUE);
8563
8564         rLen -= 8 ;
8565         if (rLen <= 0 )
8566             break ;
8567
8568         switch (p_type) {
8569             case POINTER:
8570                 if (*l == '@') {
8571                     MOVA(l);
8572                     pic14_emitcode("mov","@%s,a",rname);
8573                 } else
8574                     pic14_emitcode("mov","@%s,%s",rname,l);
8575                 break;
8576
8577             case FPOINTER:
8578                 MOVA(l);
8579                 pic14_emitcode("movx","@dptr,a");
8580                 break;
8581
8582             case GPOINTER:
8583                 MOVA(l);
8584                 DEBUGpic14_emitcode(";lcall","__gptrput");
8585                 break;  
8586         }   
8587         pic14_emitcode ("inc","%s",rname);
8588     }
8589
8590     MOVA(l);
8591
8592     /* last last was not complete */
8593     if (rLen)   {
8594         /* save the byte & read byte */
8595         switch (p_type) {
8596             case POINTER:
8597                 pic14_emitcode ("mov","b,a");
8598                 pic14_emitcode("mov","a,@%s",rname);
8599                 break;
8600
8601             case FPOINTER:
8602                 pic14_emitcode ("mov","b,a");
8603                 pic14_emitcode("movx","a,@dptr");
8604                 break;
8605
8606             case GPOINTER:
8607                 pic14_emitcode ("push","b");
8608                 pic14_emitcode ("push","acc");
8609                 pic14_emitcode ("lcall","__gptrget");
8610                 pic14_emitcode ("pop","b");
8611                 break;
8612         }
8613
8614         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8615         pic14_emitcode ("orl","a,b");
8616     }
8617
8618     if (p_type == GPOINTER)
8619         pic14_emitcode("pop","b");
8620
8621     switch (p_type) {
8622
8623     case POINTER:
8624         pic14_emitcode("mov","@%s,a",rname);
8625         break;
8626         
8627     case FPOINTER:
8628         pic14_emitcode("movx","@dptr,a");
8629         break;
8630         
8631     case GPOINTER:
8632         DEBUGpic14_emitcode(";lcall","__gptrput");
8633         break;                  
8634     }
8635 }
8636 /*-----------------------------------------------------------------*/
8637 /* genDataPointerSet - remat pointer to data space                 */
8638 /*-----------------------------------------------------------------*/
8639 static void genDataPointerSet(operand *right,
8640                               operand *result,
8641                               iCode *ic)
8642 {
8643     int size, offset = 0 ;
8644     char *l, buffer[256];
8645
8646     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8647     aopOp(right,ic,FALSE);
8648     
8649     l = aopGet(AOP(result),0,FALSE,TRUE);
8650     size = AOP_SIZE(right);
8651 /*
8652     if ( AOP_TYPE(result) == AOP_PCODE) {
8653       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8654               AOP(result)->aopu.pcop->name,
8655               PCOI(AOP(result)->aopu.pcop)->offset);
8656     }
8657 */
8658
8659     // tsd, was l+1 - the underline `_' prefix was being stripped
8660     while (size--) {
8661       if (offset) {
8662         sprintf(buffer,"(%s + %d)",l,offset);
8663         fprintf(stderr,"oops  %s\n",buffer);
8664       } else
8665         sprintf(buffer,"%s",l);
8666
8667         if (AOP_TYPE(right) == AOP_LIT) {
8668           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8669           lit = lit >> (8*offset);
8670           if(lit&0xff) {
8671             pic14_emitcode("movlw","%d",lit);
8672             pic14_emitcode("movwf","%s",buffer);
8673
8674             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8675             //emitpcode(POC_MOVWF, popRegFromString(buffer));
8676             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8677
8678           } else {
8679             pic14_emitcode("clrf","%s",buffer);
8680             //emitpcode(POC_CLRF, popRegFromString(buffer));
8681             emitpcode(POC_CLRF, popGet(AOP(result),0));
8682           }
8683         }else {
8684           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8685           pic14_emitcode("movwf","%s",buffer);
8686
8687           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8688           //emitpcode(POC_MOVWF, popRegFromString(buffer));
8689           emitpcode(POC_MOVWF, popGet(AOP(result),0));
8690
8691         }
8692
8693         offset++;
8694     }
8695
8696     freeAsmop(right,NULL,ic,TRUE);
8697     freeAsmop(result,NULL,ic,TRUE);
8698 }
8699
8700 /*-----------------------------------------------------------------*/
8701 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8702 /*-----------------------------------------------------------------*/
8703 static void genNearPointerSet (operand *right,
8704                                operand *result, 
8705                                iCode *ic)
8706 {
8707   asmop *aop = NULL;
8708   char *l;
8709   sym_link *retype;
8710   sym_link *ptype = operandType(result);
8711
8712     
8713   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8714   retype= getSpec(operandType(right));
8715
8716   aopOp(result,ic,FALSE);
8717
8718     
8719   /* if the result is rematerializable &
8720      in data space & not a bit variable */
8721   //if (AOP_TYPE(result) == AOP_IMMD &&
8722   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8723       DCL_TYPE(ptype) == POINTER   &&
8724       !IS_BITVAR(retype)) {
8725     genDataPointerSet (right,result,ic);
8726     freeAsmop(result,NULL,ic,TRUE);
8727     return;
8728   }
8729
8730   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8731   aopOp(right,ic,FALSE);
8732   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8733
8734   /* if the value is already in a pointer register
8735      then don't need anything more */
8736   if (!AOP_INPREG(AOP(result))) {
8737     /* otherwise get a free pointer register */
8738     //aop = newAsmop(0);
8739     //preg = getFreePtr(ic,&aop,FALSE);
8740     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8741     //pic14_emitcode("mov","%s,%s",
8742     //         preg->name,
8743     //         aopGet(AOP(result),0,FALSE,TRUE));
8744     //rname = preg->name ;
8745     //pic14_emitcode("movwf","fsr");
8746     emitpcode(POC_MOVFW, popGet(AOP(result),0));
8747     emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8748     emitpcode(POC_MOVFW, popGet(AOP(right),0));
8749     emitpcode(POC_MOVWF, popCopyReg(&pc_indf));
8750     goto release;
8751
8752   }// else
8753   //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8754
8755
8756   /* if bitfield then unpack the bits */
8757   if (IS_BITVAR(retype)) {
8758     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8759            "The programmer is obviously confused");
8760     //genPackBits (retype,right,rname,POINTER);
8761     exit(1);
8762   }
8763   else {
8764     /* we have can just get the values */
8765     int size = AOP_SIZE(right);
8766     int offset = 0 ;    
8767
8768     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8769     while (size--) {
8770       l = aopGet(AOP(right),offset,FALSE,TRUE);
8771       if (*l == '@' ) {
8772         //MOVA(l);
8773         //pic14_emitcode("mov","@%s,a",rname);
8774         pic14_emitcode("movf","indf,w ;1");
8775       } else {
8776
8777         if (AOP_TYPE(right) == AOP_LIT) {
8778           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8779           if(lit) {
8780             pic14_emitcode("movlw","%s",l);
8781             pic14_emitcode("movwf","indf ;2");
8782           } else 
8783             pic14_emitcode("clrf","indf");
8784         }else {
8785           pic14_emitcode("movf","%s,w",l);
8786           pic14_emitcode("movwf","indf ;2");
8787         }
8788         //pic14_emitcode("mov","@%s,%s",rname,l);
8789       }
8790       if (size)
8791         pic14_emitcode("incf","fsr,f ;3");
8792       //pic14_emitcode("inc","%s",rname);
8793       offset++;
8794     }
8795   }
8796
8797   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8798   /* now some housekeeping stuff */
8799   if (aop) {
8800     /* we had to allocate for this iCode */
8801     freeAsmop(NULL,aop,ic,TRUE);
8802   } else { 
8803     /* we did not allocate which means left
8804        already in a pointer register, then
8805        if size > 0 && this could be used again
8806        we have to point it back to where it 
8807        belongs */
8808     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8809     if (AOP_SIZE(right) > 1 &&
8810         !OP_SYMBOL(result)->remat &&
8811         ( OP_SYMBOL(result)->liveTo > ic->seq ||
8812           ic->depth )) {
8813       int size = AOP_SIZE(right) - 1;
8814       while (size--)
8815         pic14_emitcode("decf","fsr,f");
8816       //pic14_emitcode("dec","%s",rname);
8817     }
8818   }
8819
8820   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8821   /* done */
8822  release:
8823   freeAsmop(right,NULL,ic,TRUE);
8824   freeAsmop(result,NULL,ic,TRUE);
8825 }
8826
8827 /*-----------------------------------------------------------------*/
8828 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8829 /*-----------------------------------------------------------------*/
8830 static void genPagedPointerSet (operand *right,
8831                                operand *result, 
8832                                iCode *ic)
8833 {
8834     asmop *aop = NULL;
8835     regs *preg = NULL ;
8836     char *rname , *l;
8837     sym_link *retype;
8838        
8839     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8840
8841     retype= getSpec(operandType(right));
8842     
8843     aopOp(result,ic,FALSE);
8844     
8845     /* if the value is already in a pointer register
8846        then don't need anything more */
8847     if (!AOP_INPREG(AOP(result))) {
8848         /* otherwise get a free pointer register */
8849         aop = newAsmop(0);
8850         preg = getFreePtr(ic,&aop,FALSE);
8851         pic14_emitcode("mov","%s,%s",
8852                 preg->name,
8853                 aopGet(AOP(result),0,FALSE,TRUE));
8854         rname = preg->name ;
8855     } else
8856         rname = aopGet(AOP(result),0,FALSE,FALSE);
8857     
8858     freeAsmop(result,NULL,ic,TRUE);
8859     aopOp (right,ic,FALSE);
8860
8861     /* if bitfield then unpack the bits */
8862     if (IS_BITVAR(retype)) 
8863         genPackBits (retype,right,rname,PPOINTER);
8864     else {
8865         /* we have can just get the values */
8866         int size = AOP_SIZE(right);
8867         int offset = 0 ;        
8868         
8869         while (size--) {
8870             l = aopGet(AOP(right),offset,FALSE,TRUE);
8871             
8872             MOVA(l);
8873             pic14_emitcode("movx","@%s,a",rname);
8874
8875             if (size)
8876                 pic14_emitcode("inc","%s",rname);
8877
8878             offset++;
8879         }
8880     }
8881     
8882     /* now some housekeeping stuff */
8883     if (aop) {
8884         /* we had to allocate for this iCode */
8885         freeAsmop(NULL,aop,ic,TRUE);
8886     } else { 
8887         /* we did not allocate which means left
8888            already in a pointer register, then
8889            if size > 0 && this could be used again
8890            we have to point it back to where it 
8891            belongs */
8892         if (AOP_SIZE(right) > 1 &&
8893             !OP_SYMBOL(result)->remat &&
8894             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8895               ic->depth )) {
8896             int size = AOP_SIZE(right) - 1;
8897             while (size--)
8898                 pic14_emitcode("dec","%s",rname);
8899         }
8900     }
8901
8902     /* done */
8903     freeAsmop(right,NULL,ic,TRUE);
8904     
8905         
8906 }
8907
8908 /*-----------------------------------------------------------------*/
8909 /* genFarPointerSet - set value from far space                     */
8910 /*-----------------------------------------------------------------*/
8911 static void genFarPointerSet (operand *right,
8912                               operand *result, iCode *ic)
8913 {
8914     int size, offset ;
8915     sym_link *retype = getSpec(operandType(right));
8916
8917     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8918     aopOp(result,ic,FALSE);
8919
8920     /* if the operand is already in dptr 
8921     then we do nothing else we move the value to dptr */
8922     if (AOP_TYPE(result) != AOP_STR) {
8923         /* if this is remateriazable */
8924         if (AOP_TYPE(result) == AOP_IMMD)
8925             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8926         else { /* we need to get it byte by byte */
8927             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8928             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8929             if (options.model == MODEL_FLAT24)
8930             {
8931                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8932             }
8933         }
8934     }
8935     /* so dptr know contains the address */
8936     freeAsmop(result,NULL,ic,TRUE);
8937     aopOp(right,ic,FALSE);
8938
8939     /* if bit then unpack */
8940     if (IS_BITVAR(retype)) 
8941         genPackBits(retype,right,"dptr",FPOINTER);
8942     else {
8943         size = AOP_SIZE(right);
8944         offset = 0 ;
8945
8946         while (size--) {
8947             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8948             MOVA(l);
8949             pic14_emitcode("movx","@dptr,a");
8950             if (size)
8951                 pic14_emitcode("inc","dptr");
8952         }
8953     }
8954
8955     freeAsmop(right,NULL,ic,TRUE);
8956 }
8957
8958 /*-----------------------------------------------------------------*/
8959 /* genGenPointerSet - set value from generic pointer space         */
8960 /*-----------------------------------------------------------------*/
8961 static void genGenPointerSet (operand *right,
8962                               operand *result, iCode *ic)
8963 {
8964   int size, offset ;
8965   sym_link *retype = getSpec(operandType(right));
8966
8967   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8968
8969   aopOp(result,ic,FALSE);
8970   aopOp(right,ic,FALSE);
8971   size = AOP_SIZE(right);
8972
8973   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8974
8975   /* if the operand is already in dptr 
8976      then we do nothing else we move the value to dptr */
8977   if (AOP_TYPE(result) != AOP_STR) {
8978     /* if this is remateriazable */
8979     if (AOP_TYPE(result) == AOP_IMMD) {
8980       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8981       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8982     }
8983     else { /* we need to get it byte by byte */
8984       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8985       size = AOP_SIZE(right);
8986       offset = 0 ;
8987
8988       /* hack hack! see if this the FSR. If so don't load W */
8989       if(AOP_TYPE(right) != AOP_ACC) {
8990
8991
8992         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8993         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8994
8995         if(AOP_SIZE(result) > 1) {
8996           emitpcode(POC_BCF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8997           emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8998           emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
8999
9000         }
9001
9002         //if(size==2)
9003         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
9004         //if(size==4) {
9005         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
9006         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
9007         //}
9008
9009         while(size--) {
9010           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
9011           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9012           
9013           if(size)
9014             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9015         }
9016
9017
9018         goto release;
9019       } 
9020
9021       if(aopIdx(AOP(result),0) != 4) {
9022
9023         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9024         goto release;
9025       }
9026
9027       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9028       goto release;
9029
9030     }
9031   }
9032   /* so dptr know contains the address */
9033
9034
9035   /* if bit then unpack */
9036   if (IS_BITVAR(retype)) 
9037     genPackBits(retype,right,"dptr",GPOINTER);
9038   else {
9039     size = AOP_SIZE(right);
9040     offset = 0 ;
9041
9042   DEBUGpic14_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9043
9044     while (size--) {
9045
9046       emitpcode(POC_MOVFW,popGet(AOP(result),offset));
9047       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9048
9049       if (AOP_TYPE(right) == AOP_LIT) 
9050         emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9051       else
9052         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9053
9054       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9055
9056       offset++;
9057     }
9058   }
9059
9060  release:
9061   freeAsmop(right,NULL,ic,TRUE);
9062   freeAsmop(result,NULL,ic,TRUE);
9063 }
9064
9065 /*-----------------------------------------------------------------*/
9066 /* genPointerSet - stores the value into a pointer location        */
9067 /*-----------------------------------------------------------------*/
9068 static void genPointerSet (iCode *ic)
9069 {    
9070     operand *right, *result ;
9071     sym_link *type, *etype;
9072     int p_type;
9073
9074     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9075
9076     right = IC_RIGHT(ic);
9077     result = IC_RESULT(ic) ;
9078
9079     /* depending on the type of pointer we need to
9080     move it to the correct pointer register */
9081     type = operandType(result);
9082     etype = getSpec(type);
9083     /* if left is of type of pointer then it is simple */
9084     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9085         p_type = DCL_TYPE(type);
9086     }
9087     else {
9088         /* we have to go by the storage class */
9089         p_type = PTR_TYPE(SPEC_OCLS(etype));
9090
9091 /*      if (SPEC_OCLS(etype)->codesp ) { */
9092 /*          p_type = CPOINTER ;  */
9093 /*      } */
9094 /*      else */
9095 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9096 /*              p_type = FPOINTER ; */
9097 /*          else */
9098 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9099 /*                  p_type = PPOINTER ; */
9100 /*              else */
9101 /*                  if (SPEC_OCLS(etype) == idata ) */
9102 /*                      p_type = IPOINTER ; */
9103 /*                  else */
9104 /*                      p_type = POINTER ; */
9105     }
9106
9107     /* now that we have the pointer type we assign
9108     the pointer values */
9109     switch (p_type) {
9110
9111     case POINTER:
9112     case IPOINTER:
9113         genNearPointerSet (right,result,ic);
9114         break;
9115
9116     case PPOINTER:
9117         genPagedPointerSet (right,result,ic);
9118         break;
9119
9120     case FPOINTER:
9121         genFarPointerSet (right,result,ic);
9122         break;
9123
9124     case GPOINTER:
9125         genGenPointerSet (right,result,ic);
9126         break;
9127
9128     default:
9129       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9130               "genPointerSet: illegal pointer type");
9131     }
9132 }
9133
9134 /*-----------------------------------------------------------------*/
9135 /* genIfx - generate code for Ifx statement                        */
9136 /*-----------------------------------------------------------------*/
9137 static void genIfx (iCode *ic, iCode *popIc)
9138 {
9139   operand *cond = IC_COND(ic);
9140   int isbit =0;
9141
9142   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9143
9144   aopOp(cond,ic,FALSE);
9145
9146   /* get the value into acc */
9147   if (AOP_TYPE(cond) != AOP_CRY)
9148     pic14_toBoolean(cond);
9149   else
9150     isbit = 1;
9151   /* the result is now in the accumulator */
9152   freeAsmop(cond,NULL,ic,TRUE);
9153
9154   /* if there was something to be popped then do it */
9155   if (popIc)
9156     genIpop(popIc);
9157
9158   /* if the condition is  a bit variable */
9159   if (isbit && IS_ITEMP(cond) && 
9160       SPIL_LOC(cond)) {
9161     genIfxJump(ic,SPIL_LOC(cond)->rname);
9162     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9163   }
9164   else {
9165     if (isbit && !IS_ITEMP(cond))
9166       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9167     else
9168       genIfxJump(ic,"a");
9169   }
9170   ic->generated = 1;
9171
9172 }
9173
9174 /*-----------------------------------------------------------------*/
9175 /* genAddrOf - generates code for address of                       */
9176 /*-----------------------------------------------------------------*/
9177 static void genAddrOf (iCode *ic)
9178 {
9179   operand *right, *result, *left;
9180   int size, offset ;
9181
9182   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9183
9184
9185   //aopOp(IC_RESULT(ic),ic,FALSE);
9186
9187   aopOp((left=IC_LEFT(ic)),ic,FALSE);
9188   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9189   aopOp((result=IC_RESULT(ic)),ic,TRUE);
9190
9191   DEBUGpic14_AopType(__LINE__,left,right,result);
9192
9193   size = AOP_SIZE(IC_RESULT(ic));
9194   offset = 0;
9195
9196   while (size--) {
9197     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9198     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9199     offset++;
9200   }
9201
9202   freeAsmop(left,NULL,ic,FALSE);
9203   freeAsmop(result,NULL,ic,TRUE);
9204
9205 }
9206
9207 #if 0
9208 /*-----------------------------------------------------------------*/
9209 /* genFarFarAssign - assignment when both are in far space         */
9210 /*-----------------------------------------------------------------*/
9211 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9212 {
9213     int size = AOP_SIZE(right);
9214     int offset = 0;
9215     char *l ;
9216     /* first push the right side on to the stack */
9217     while (size--) {
9218         l = aopGet(AOP(right),offset++,FALSE,FALSE);
9219         MOVA(l);
9220         pic14_emitcode ("push","acc");
9221     }
9222     
9223     freeAsmop(right,NULL,ic,FALSE);
9224     /* now assign DPTR to result */
9225     aopOp(result,ic,FALSE);
9226     size = AOP_SIZE(result);
9227     while (size--) {
9228         pic14_emitcode ("pop","acc");
9229         aopPut(AOP(result),"a",--offset);
9230     }
9231     freeAsmop(result,NULL,ic,FALSE);
9232         
9233 }
9234 #endif
9235
9236 /*-----------------------------------------------------------------*/
9237 /* genAssign - generate code for assignment                        */
9238 /*-----------------------------------------------------------------*/
9239 static void genAssign (iCode *ic)
9240 {
9241   operand *result, *right;
9242   int size, offset,know_W;
9243   unsigned long lit = 0L;
9244
9245   result = IC_RESULT(ic);
9246   right  = IC_RIGHT(ic) ;
9247
9248   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9249
9250   /* if they are the same */
9251   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9252     return ;
9253
9254   aopOp(right,ic,FALSE);
9255   aopOp(result,ic,TRUE);
9256
9257   DEBUGpic14_AopType(__LINE__,NULL,right,result);
9258
9259   /* if they are the same registers */
9260   if (pic14_sameRegs(AOP(right),AOP(result)))
9261     goto release;
9262
9263   /* if the result is a bit */
9264   if (AOP_TYPE(result) == AOP_CRY) {
9265
9266     /* if the right size is a literal then
9267        we know what the value is */
9268     if (AOP_TYPE(right) == AOP_LIT) {
9269           
9270       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9271                   popGet(AOP(result),0));
9272
9273       if (((int) operandLitValue(right))) 
9274         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9275                        AOP(result)->aopu.aop_dir,
9276                        AOP(result)->aopu.aop_dir);
9277       else
9278         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9279                        AOP(result)->aopu.aop_dir,
9280                        AOP(result)->aopu.aop_dir);
9281       goto release;
9282     }
9283
9284     /* the right is also a bit variable */
9285     if (AOP_TYPE(right) == AOP_CRY) {
9286       emitpcode(POC_BCF,    popGet(AOP(result),0));
9287       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9288       emitpcode(POC_BSF,    popGet(AOP(result),0));
9289
9290       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9291                      AOP(result)->aopu.aop_dir,
9292                      AOP(result)->aopu.aop_dir);
9293       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9294                      AOP(right)->aopu.aop_dir,
9295                      AOP(right)->aopu.aop_dir);
9296       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9297                      AOP(result)->aopu.aop_dir,
9298                      AOP(result)->aopu.aop_dir);
9299       goto release ;
9300     }
9301
9302     /* we need to or */
9303     emitpcode(POC_BCF,    popGet(AOP(result),0));
9304     pic14_toBoolean(right);
9305     emitSKPZ;
9306     emitpcode(POC_BSF,    popGet(AOP(result),0));
9307     //aopPut(AOP(result),"a",0);
9308     goto release ;
9309   }
9310
9311   /* bit variables done */
9312   /* general case */
9313   size = AOP_SIZE(result);
9314   offset = 0 ;
9315   if(AOP_TYPE(right) == AOP_LIT)
9316     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9317
9318   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9319   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9320     if(aopIdx(AOP(result),0) == 4) {
9321   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9322       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9323       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9324       goto release;
9325     } else
9326       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9327   }
9328
9329   know_W=-1;
9330   while (size--) {
9331   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9332     if(AOP_TYPE(right) == AOP_LIT) {
9333       if(lit&0xff) {
9334         if(know_W != (int)(lit&0xff))
9335           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9336         know_W = lit&0xff;
9337         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9338       } else
9339         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9340
9341       lit >>= 8;
9342
9343     } else if (AOP_TYPE(right) == AOP_CRY) {
9344       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9345       if(offset == 0) {
9346         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9347         emitpcode(POC_INCF, popGet(AOP(result),0));
9348       }
9349     } else {
9350       mov2w (AOP(right), offset);
9351       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9352     }
9353             
9354     offset++;
9355   }
9356
9357     
9358  release:
9359   freeAsmop (right,NULL,ic,FALSE);
9360   freeAsmop (result,NULL,ic,TRUE);
9361 }   
9362
9363 /*-----------------------------------------------------------------*/
9364 /* genJumpTab - genrates code for jump table                       */
9365 /*-----------------------------------------------------------------*/
9366 static void genJumpTab (iCode *ic)
9367 {
9368     symbol *jtab;
9369     char *l;
9370
9371     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9372
9373     aopOp(IC_JTCOND(ic),ic,FALSE);
9374     /* get the condition into accumulator */
9375     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9376     MOVA(l);
9377     /* multiply by three */
9378     pic14_emitcode("add","a,acc");
9379     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9380
9381     jtab = newiTempLabel(NULL);
9382     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9383     pic14_emitcode("jmp","@a+dptr");
9384     pic14_emitcode("","%05d_DS_:",jtab->key+100);
9385
9386     emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9387     emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9388     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9389     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9390     emitSKPNC;
9391     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9392     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9393     emitpLabel(jtab->key);
9394
9395     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9396
9397     /* now generate the jump labels */
9398     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9399          jtab = setNextItem(IC_JTLABELS(ic))) {
9400         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9401         emitpcode(POC_GOTO,popGetLabel(jtab->key));
9402         
9403     }
9404
9405 }
9406
9407 /*-----------------------------------------------------------------*/
9408 /* genMixedOperation - gen code for operators between mixed types  */
9409 /*-----------------------------------------------------------------*/
9410 /*
9411   TSD - Written for the PIC port - but this unfortunately is buggy.
9412   This routine is good in that it is able to efficiently promote 
9413   types to different (larger) sizes. Unfortunately, the temporary
9414   variables that are optimized out by this routine are sometimes
9415   used in other places. So until I know how to really parse the 
9416   iCode tree, I'm going to not be using this routine :(.
9417 */
9418 static int genMixedOperation (iCode *ic)
9419 {
9420 #if 0
9421   operand *result = IC_RESULT(ic);
9422   sym_link *ctype = operandType(IC_LEFT(ic));
9423   operand *right = IC_RIGHT(ic);
9424   int ret = 0;
9425   int big,small;
9426   int offset;
9427
9428   iCode *nextic;
9429   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9430
9431   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9432
9433   nextic = ic->next;
9434   if(!nextic)
9435     return 0;
9436
9437   nextright = IC_RIGHT(nextic);
9438   nextleft  = IC_LEFT(nextic);
9439   nextresult = IC_RESULT(nextic);
9440
9441   aopOp(right,ic,FALSE);
9442   aopOp(result,ic,FALSE);
9443   aopOp(nextright,  nextic, FALSE);
9444   aopOp(nextleft,   nextic, FALSE);
9445   aopOp(nextresult, nextic, FALSE);
9446
9447   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9448
9449     operand *t = right;
9450     right = nextright;
9451     nextright = t; 
9452
9453     pic14_emitcode(";remove right +","");
9454
9455   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9456 /*
9457     operand *t = right;
9458     right = nextleft;
9459     nextleft = t; 
9460 */
9461     pic14_emitcode(";remove left +","");
9462   } else
9463     return 0;
9464
9465   big = AOP_SIZE(nextleft);
9466   small = AOP_SIZE(nextright);
9467
9468   switch(nextic->op) {
9469
9470   case '+':
9471     pic14_emitcode(";optimize a +","");
9472     /* if unsigned or not an integral type */
9473     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9474       pic14_emitcode(";add a bit to something","");
9475     } else {
9476
9477       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9478
9479       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9480         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9481         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9482       } else
9483         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9484
9485       offset = 0;
9486       while(--big) {
9487
9488         offset++;
9489
9490         if(--small) {
9491           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9492             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9493             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9494           }
9495
9496           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9497           emitSKPNC;
9498           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9499                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9500                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9501           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9502           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9503
9504         } else {
9505           pic14_emitcode("rlf","known_zero,w");
9506
9507           /*
9508             if right is signed
9509               btfsc  right,7
9510                addlw ff
9511           */
9512           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9513             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9514             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9515           } else {
9516             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9517           }
9518         }
9519       }
9520       ret = 1;
9521     }
9522   }
9523   ret = 1;
9524
9525 release:
9526   freeAsmop(right,NULL,ic,TRUE);
9527   freeAsmop(result,NULL,ic,TRUE);
9528   freeAsmop(nextright,NULL,ic,TRUE);
9529   freeAsmop(nextleft,NULL,ic,TRUE);
9530   if(ret)
9531     nextic->generated = 1;
9532
9533   return ret;
9534 #else
9535   return 0;
9536 #endif
9537 }
9538 /*-----------------------------------------------------------------*/
9539 /* genCast - gen code for casting                                  */
9540 /*-----------------------------------------------------------------*/
9541 static void genCast (iCode *ic)
9542 {
9543     operand *result = IC_RESULT(ic);
9544     sym_link *ctype = operandType(IC_LEFT(ic));
9545     sym_link *rtype = operandType(IC_RIGHT(ic));
9546     operand *right = IC_RIGHT(ic);
9547     int size, offset ;
9548
9549     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9550     /* if they are equivalent then do nothing */
9551     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9552         return ;
9553
9554     aopOp(right,ic,FALSE) ;
9555     aopOp(result,ic,FALSE);
9556
9557     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9558
9559     /* if the result is a bit */
9560     if (AOP_TYPE(result) == AOP_CRY) {
9561         /* if the right size is a literal then
9562         we know what the value is */
9563       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9564         if (AOP_TYPE(right) == AOP_LIT) {
9565
9566           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9567                       popGet(AOP(result),0));
9568
9569             if (((int) operandLitValue(right))) 
9570               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9571                        AOP(result)->aopu.aop_dir,
9572                        AOP(result)->aopu.aop_dir);
9573             else
9574               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9575                        AOP(result)->aopu.aop_dir,
9576                        AOP(result)->aopu.aop_dir);
9577
9578             goto release;
9579         }
9580
9581         /* the right is also a bit variable */
9582         if (AOP_TYPE(right) == AOP_CRY) {
9583
9584           emitCLRC;
9585           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9586
9587           pic14_emitcode("clrc","");
9588           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9589                    AOP(right)->aopu.aop_dir,
9590                    AOP(right)->aopu.aop_dir);
9591             aopPut(AOP(result),"c",0);
9592             goto release ;
9593         }
9594
9595         /* we need to or */
9596         if (AOP_TYPE(right) == AOP_REG) {
9597           emitpcode(POC_BCF,    popGet(AOP(result),0));
9598           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9599           emitpcode(POC_BSF,    popGet(AOP(result),0));
9600         }
9601         pic14_toBoolean(right);
9602         aopPut(AOP(result),"a",0);
9603         goto release ;
9604     }
9605
9606     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9607       int offset = 1;
9608       size = AOP_SIZE(result);
9609
9610       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9611
9612       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9613       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9614       emitpcode(POC_INCF,   popGet(AOP(result),0));
9615
9616       while (size--)
9617         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9618
9619       goto release;
9620     }
9621
9622     /* if they are the same size : or less */
9623     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9624
9625         /* if they are in the same place */
9626       if (pic14_sameRegs(AOP(right),AOP(result)))
9627         goto release;
9628
9629       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9630 #if 0
9631       if (IS_PTR_CONST(rtype))
9632 #else
9633       if (IS_CODEPTR(rtype))
9634 #endif
9635         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9636 #if 0
9637       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9638 #else
9639       if (IS_CODEPTR(operandType(IC_RESULT(ic))))
9640 #endif
9641         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9642
9643       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9644         emitpcode(POC_MOVLW, popGet(AOP(right),0));
9645         emitpcode(POC_MOVWF, popGet(AOP(result),0));
9646         emitpcode(POC_MOVLW, popGet(AOP(right),1));
9647         emitpcode(POC_MOVWF, popGet(AOP(result),1));
9648         if(AOP_SIZE(result) <2)
9649           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9650
9651       } else {
9652
9653         /* if they in different places then copy */
9654         size = AOP_SIZE(result);
9655         offset = 0 ;
9656         while (size--) {
9657           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9658           emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9659
9660           //aopPut(AOP(result),
9661           // aopGet(AOP(right),offset,FALSE,FALSE),
9662           // offset);
9663
9664           offset++;
9665         }
9666       }
9667       goto release;
9668     }
9669
9670
9671     /* if the result is of type pointer */
9672     if (IS_PTR(ctype)) {
9673
9674         int p_type;
9675         sym_link *type = operandType(right);
9676         sym_link *etype = getSpec(type);
9677       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9678
9679         /* pointer to generic pointer */
9680         if (IS_GENPTR(ctype)) {
9681             char *l = zero;
9682             
9683             if (IS_PTR(type)) 
9684                 p_type = DCL_TYPE(type);
9685             else {
9686                 /* we have to go by the storage class */
9687                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9688
9689 /*              if (SPEC_OCLS(etype)->codesp )  */
9690 /*                  p_type = CPOINTER ;  */
9691 /*              else */
9692 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9693 /*                      p_type = FPOINTER ; */
9694 /*                  else */
9695 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9696 /*                          p_type = PPOINTER; */
9697 /*                      else */
9698 /*                          if (SPEC_OCLS(etype) == idata ) */
9699 /*                              p_type = IPOINTER ; */
9700 /*                          else */
9701 /*                              p_type = POINTER ; */
9702             }
9703                 
9704             /* the first two bytes are known */
9705       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
9706             size = GPTRSIZE - 1; 
9707             offset = 0 ;
9708             while (size--) {
9709               if(offset < AOP_SIZE(right)) {
9710       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
9711                 if ((AOP_TYPE(right) == AOP_PCODE) && 
9712                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9713                   emitpcode(POC_MOVLW, popGet(AOP(right),offset));
9714                   emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9715                 } else { 
9716                   aopPut(AOP(result),
9717                          aopGet(AOP(right),offset,FALSE,FALSE),
9718                          offset);
9719                 }
9720               } else 
9721                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9722               offset++;
9723             }
9724             /* the last byte depending on type */
9725             switch (p_type) {
9726             case IPOINTER:
9727             case POINTER:
9728                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9729                 break;
9730             case FPOINTER:
9731               pic14_emitcode(";BUG!? ","%d",__LINE__);
9732                 l = one;
9733                 break;
9734             case CPOINTER:
9735               pic14_emitcode(";BUG!? ","%d",__LINE__);
9736                 l = "#0x02";
9737                 break;                          
9738             case PPOINTER:
9739               pic14_emitcode(";BUG!? ","%d",__LINE__);
9740                 l = "#0x03";
9741                 break;
9742                 
9743             default:
9744                 /* this should never happen */
9745                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9746                        "got unknown pointer type");
9747                 exit(1);
9748             }
9749             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9750             goto release ;
9751         }
9752         
9753         /* just copy the pointers */
9754         size = AOP_SIZE(result);
9755         offset = 0 ;
9756         while (size--) {
9757             aopPut(AOP(result),
9758                    aopGet(AOP(right),offset,FALSE,FALSE),
9759                    offset);
9760             offset++;
9761         }
9762         goto release ;
9763     }
9764     
9765
9766
9767     /* so we now know that the size of destination is greater
9768     than the size of the source.
9769     Now, if the next iCode is an operator then we might be
9770     able to optimize the operation without performing a cast.
9771     */
9772     if(genMixedOperation(ic))
9773       goto release;
9774
9775     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9776     
9777     /* we move to result for the size of source */
9778     size = AOP_SIZE(right);
9779     offset = 0 ;
9780     while (size--) {
9781       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9782       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9783       offset++;
9784     }
9785
9786     /* now depending on the sign of the destination */
9787     size = AOP_SIZE(result) - AOP_SIZE(right);
9788     /* if unsigned or not an integral type */
9789     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9790       while (size--)
9791         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9792     } else {
9793       /* we need to extend the sign :{ */
9794
9795       if(size == 1) {
9796         /* Save one instruction of casting char to int */
9797         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9798         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9799         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9800       } else {
9801         emitpcodeNULLop(POC_CLRW);
9802
9803         if(offset)
9804           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9805         else
9806           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9807         
9808         emitpcode(POC_MOVLW,   popGetLit(0xff));
9809
9810         while (size--)
9811           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9812       }
9813     }
9814
9815 release:
9816     freeAsmop(right,NULL,ic,TRUE);
9817     freeAsmop(result,NULL,ic,TRUE);
9818
9819 }
9820
9821 /*-----------------------------------------------------------------*/
9822 /* genDjnz - generate decrement & jump if not zero instrucion      */
9823 /*-----------------------------------------------------------------*/
9824 static int genDjnz (iCode *ic, iCode *ifx)
9825 {
9826     symbol *lbl, *lbl1;
9827     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9828
9829     if (!ifx)
9830         return 0;
9831     
9832     /* if the if condition has a false label
9833        then we cannot save */
9834     if (IC_FALSE(ifx))
9835         return 0;
9836
9837     /* if the minus is not of the form 
9838        a = a - 1 */
9839     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9840         !IS_OP_LITERAL(IC_RIGHT(ic)))
9841         return 0;
9842
9843     if (operandLitValue(IC_RIGHT(ic)) != 1)
9844         return 0;
9845
9846     /* if the size of this greater than one then no
9847        saving */
9848     if (getSize(operandType(IC_RESULT(ic))) > 1)
9849         return 0;
9850
9851     /* otherwise we can save BIG */
9852     lbl = newiTempLabel(NULL);
9853     lbl1= newiTempLabel(NULL);
9854
9855     aopOp(IC_RESULT(ic),ic,FALSE);
9856     
9857     if (IS_AOP_PREG(IC_RESULT(ic))) {
9858         pic14_emitcode("dec","%s",
9859                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9860         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9861         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9862     } else {    
9863
9864
9865       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9866       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9867
9868       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9869       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9870
9871     }
9872 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9873 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9874 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9875 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9876
9877     
9878     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9879     ifx->generated = 1;
9880     return 1;
9881 }
9882
9883 /*-----------------------------------------------------------------*/
9884 /* genReceive - generate code for a receive iCode                  */
9885 /*-----------------------------------------------------------------*/
9886 static void genReceive (iCode *ic)
9887 {
9888   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9889
9890   if (isOperandInFarSpace(IC_RESULT(ic)) &&
9891       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9892         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9893
9894     int size = getSize(operandType(IC_RESULT(ic)));
9895     int offset =  fReturnSizePic - size;
9896     while (size--) {
9897       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9898                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9899       offset++;
9900     }
9901     aopOp(IC_RESULT(ic),ic,FALSE);
9902     size = AOP_SIZE(IC_RESULT(ic));
9903     offset = 0;
9904     while (size--) {
9905       pic14_emitcode ("pop","acc");
9906       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9907     }
9908
9909   } else {
9910     _G.accInUse++;
9911     aopOp(IC_RESULT(ic),ic,FALSE);
9912     _G.accInUse--;
9913     assignResultValue(IC_RESULT(ic));
9914   }
9915
9916   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9917 }
9918
9919 /*-----------------------------------------------------------------*/
9920 /* genDummyRead - generate code for dummy read of volatiles        */
9921 /*-----------------------------------------------------------------*/
9922 static void
9923 genDummyRead (iCode * ic)
9924 {
9925   pic14_emitcode ("; genDummyRead","");
9926   pic14_emitcode ("; not implemented","");
9927
9928   ic = ic;
9929 }
9930
9931 /*-----------------------------------------------------------------*/
9932 /* genpic14Code - generate code for pic14 based controllers        */
9933 /*-----------------------------------------------------------------*/
9934 /*
9935  * At this point, ralloc.c has gone through the iCode and attempted
9936  * to optimize in a way suitable for a PIC. Now we've got to generate
9937  * PIC instructions that correspond to the iCode.
9938  *
9939  * Once the instructions are generated, we'll pass through both the
9940  * peep hole optimizer and the pCode optimizer.
9941  *-----------------------------------------------------------------*/
9942
9943 void genpic14Code (iCode *lic)
9944 {
9945     iCode *ic;
9946     int cln = 0;
9947
9948     lineHead = lineCurr = NULL;
9949
9950     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9951     addpBlock(pb);
9952
9953     /* if debug information required */
9954     if (options.debug && currFunc) { 
9955       if (currFunc) {
9956         debugFile->writeFunction(currFunc);
9957         _G.debugLine = 1;
9958         if (IS_STATIC(currFunc->etype)) {
9959           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9960           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9961         } else {
9962           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9963           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9964         }
9965         _G.debugLine = 0;
9966       }
9967     }
9968
9969
9970     for (ic = lic ; ic ; ic = ic->next ) {
9971
9972       DEBUGpic14_emitcode(";ic","");
9973         if ( cln != ic->lineno ) {
9974             if ( options.debug ) {
9975                 _G.debugLine = 1;
9976                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9977                          FileBaseName(ic->filename),ic->lineno,
9978                          ic->level,ic->block);
9979                 _G.debugLine = 0;
9980             }
9981             /*
9982               pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9983               pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9984               printCLine(ic->filename, ic->lineno));
9985             */
9986             if (!options.noCcodeInAsm) {
9987               addpCode2pBlock(pb,
9988                               newpCodeCSource(ic->lineno, 
9989                                               ic->filename, 
9990                                               printCLine(ic->filename, ic->lineno)));
9991             }
9992
9993             cln = ic->lineno ;
9994         }
9995
9996         // if you want printILine too, look at ../mcs51/gen.c, i don't understand this :)
9997
9998         /* if the result is marked as
9999            spilt and rematerializable or code for
10000            this has already been generated then
10001            do nothing */
10002         if (resultRemat(ic) || ic->generated ) 
10003             continue ;
10004         
10005         /* depending on the operation */
10006         switch (ic->op) {
10007         case '!' :
10008             genNot(ic);
10009             break;
10010             
10011         case '~' :
10012             genCpl(ic);
10013             break;
10014             
10015         case UNARYMINUS:
10016             genUminus (ic);
10017             break;
10018             
10019         case IPUSH:
10020             genIpush (ic);
10021             break;
10022             
10023         case IPOP:
10024             /* IPOP happens only when trying to restore a 
10025                spilt live range, if there is an ifx statement
10026                following this pop then the if statement might
10027                be using some of the registers being popped which
10028                would destory the contents of the register so
10029                we need to check for this condition and handle it */
10030             if (ic->next            && 
10031                 ic->next->op == IFX &&
10032                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10033                 genIfx (ic->next,ic);
10034             else
10035                 genIpop (ic);
10036             break; 
10037             
10038         case CALL:
10039             genCall (ic);
10040             break;
10041             
10042         case PCALL:
10043             genPcall (ic);
10044             break;
10045             
10046         case FUNCTION:
10047             genFunction (ic);
10048             break;
10049             
10050         case ENDFUNCTION:
10051             genEndFunction (ic);
10052             break;
10053             
10054         case RETURN:
10055             genRet (ic);
10056             break;
10057             
10058         case LABEL:
10059             genLabel (ic);
10060             break;
10061             
10062         case GOTO:
10063             genGoto (ic);
10064             break;
10065             
10066         case '+' :
10067             genPlus (ic) ;
10068             break;
10069             
10070         case '-' :
10071             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10072                 genMinus (ic);
10073             break;
10074             
10075         case '*' :
10076             genMult (ic);
10077             break;
10078             
10079         case '/' :
10080             genDiv (ic) ;
10081             break;
10082             
10083         case '%' :
10084             genMod (ic);
10085             break;
10086             
10087         case '>' :
10088             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10089             break;
10090             
10091         case '<' :
10092             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10093             break;
10094             
10095         case LE_OP:
10096         case GE_OP:
10097         case NE_OP:
10098             
10099             /* note these two are xlated by algebraic equivalence
10100                during parsing SDCC.y */
10101             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10102                    "got '>=' or '<=' shouldn't have come here");
10103             break;      
10104             
10105         case EQ_OP:
10106             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10107             break;          
10108             
10109         case AND_OP:
10110             genAndOp (ic);
10111             break;
10112             
10113         case OR_OP:
10114             genOrOp (ic);
10115             break;
10116             
10117         case '^' :
10118             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10119             break;
10120             
10121         case '|' :
10122                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10123             break;
10124             
10125         case BITWISEAND:
10126             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10127             break;
10128             
10129         case INLINEASM:
10130             genInline (ic);
10131             break;
10132             
10133         case RRC:
10134             genRRC (ic);
10135             break;
10136             
10137         case RLC:
10138             genRLC (ic);
10139             break;
10140             
10141         case GETHBIT:
10142             genGetHbit (ic);
10143             break;
10144             
10145         case LEFT_OP:
10146             genLeftShift (ic);
10147             break;
10148             
10149         case RIGHT_OP:
10150             genRightShift (ic);
10151             break;
10152             
10153         case GET_VALUE_AT_ADDRESS:
10154             genPointerGet(ic);
10155             break;
10156             
10157         case '=' :
10158             if (POINTER_SET(ic))
10159                 genPointerSet(ic);
10160             else
10161                 genAssign(ic);
10162             break;
10163             
10164         case IFX:
10165             genIfx (ic,NULL);
10166             break;
10167             
10168         case ADDRESS_OF:
10169             genAddrOf (ic);
10170             break;
10171             
10172         case JUMPTABLE:
10173             genJumpTab (ic);
10174             break;
10175             
10176         case CAST:
10177             genCast (ic);
10178             break;
10179             
10180         case RECEIVE:
10181             genReceive(ic);
10182             break;
10183             
10184         case SEND:
10185             addSet(&_G.sendSet,ic);
10186             break;
10187
10188         case DUMMY_READ_VOLATILE:
10189           genDummyRead (ic);
10190           break;
10191
10192         default :
10193             ic = ic;
10194         }
10195     }
10196
10197
10198     /* now we are ready to call the
10199        peep hole optimizer */
10200     if (!options.nopeep) {
10201       peepHole (&lineHead);
10202     }
10203     /* now do the actual printing */
10204     printLine (lineHead,codeOutFile);
10205
10206 #ifdef PCODE_DEBUG
10207     DFPRINTF((stderr,"printing pBlock\n\n"));
10208     printpBlock(stdout,pb);
10209 #endif
10210
10211     return;
10212 }