Added support for multiplication. Fixed peep hole bugs (and more functionality to...
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
29                 Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #include "common.h"
57 #include "SDCCpeeph.h"
58 #include "ralloc.h"
59 #include "pcode.h"
60 #include "gen.h"
61
62
63 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
65 void genMult8X8_8 (operand *, operand *,operand *);
66
67 static int labelOffset=0;
68 static int debug_verbose=1;
69 static int optimized_for_speed = 0;
70
71 /* max_key keeps track of the largest label number used in 
72    a function. This is then used to adjust the label offset
73    for the next function.
74 */
75 static int max_key=0;
76 static int GpsuedoStkPtr=0;
77
78 pCodeOp *popGetImmd(char *name, unsigned int offset);
79 unsigned int pic14aopLiteral (value *val, int offset);
80 const char *AopType(short type);
81 static iCode *ifxForOp ( operand *op, iCode *ic );
82
83 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
84
85 /* this is the down and dirty file with all kinds of 
86    kludgy & hacky stuff. This is what it is all about
87    CODE GENERATION for a specific MCU . some of the
88    routines may be reusable, will have to see */
89
90 static char *zero = "#0x00";
91 static char *one  = "#0x01";
92 static char *spname = "sp";
93
94 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
95 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
96 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
97 static char **fReturn = fReturnpic14;
98
99 static char *accUse[] = {"a","b"};
100
101 //static short rbank = -1;
102
103 static struct {
104     short r0Pushed;
105     short r1Pushed;
106     short accInUse;
107     short inLine;
108     short debugLine;
109     short nRegsSaved;
110     set *sendSet;
111 } _G;
112
113 /* Resolved ifx structure. This structure stores information
114    about an iCode ifx that makes it easier to generate code.
115 */
116 typedef struct resolvedIfx {
117   symbol *lbl;     /* pointer to a label */
118   int condition;   /* true or false ifx */
119   int generated;   /* set true when the code associated with the ifx
120                     * is generated */
121 } resolvedIfx;
122
123 extern int pic14_ptrRegReq ;
124 extern int pic14_nRegs;
125 extern FILE *codeOutFile;
126 static void saverbank (int, iCode *,bool);
127
128 static lineNode *lineHead = NULL;
129 static lineNode *lineCurr = NULL;
130
131 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
132 0xE0, 0xC0, 0x80, 0x00};
133 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
134 0x07, 0x03, 0x01, 0x00};
135
136 static  pBlock *pb;
137
138 /*-----------------------------------------------------------------*/
139 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
140 /*                 exponent of 2 is returned, otherwise -1 is      */
141 /*                 returned.                                       */
142 /* note that this is similar to the function `powof2' in SDCCsymt  */
143 /* if(n == 2^y)                                                    */
144 /*   return y;                                                     */
145 /* return -1;                                                      */
146 /*-----------------------------------------------------------------*/
147 static int my_powof2 (unsigned long num)
148 {
149   if(num) {
150     if( (num & (num-1)) == 0) {
151       int nshifts = -1;
152       while(num) {
153         num>>=1;
154         nshifts++;
155       }
156       return nshifts;
157     }
158   }
159
160   return -1;
161 }
162
163 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
164 {
165
166   DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
167                        line_no,
168                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
169                        ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
170                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
171                        ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
172                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
173                        ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
174                        ((result) ? AOP_SIZE(result) : 0));
175
176 }
177
178 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
179 {
180
181   DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
182                        line_no,
183                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
184                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
185                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
186                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
187                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
188                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
189
190 }
191
192 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
193 {
194     va_list ap;
195     char lb[INITIAL_INLINEASM];  
196     char *lbp = lb;
197
198     if(!debug_verbose)
199       return;
200
201     va_start(ap,fmt);   
202
203     if (inst && *inst) {
204         if (fmt && *fmt)
205             sprintf(lb,"%s\t",inst);
206         else
207             sprintf(lb,"%s",inst);
208         vsprintf(lb+(strlen(lb)),fmt,ap);
209     }  else
210         vsprintf(lb,fmt,ap);
211
212     while (isspace(*lbp)) lbp++;
213
214     if (lbp && *lbp) 
215         lineCurr = (lineCurr ?
216                     connectLine(lineCurr,newLineNode(lb)) :
217                     (lineHead = newLineNode(lb)));
218     lineCurr->isInline = _G.inLine;
219     lineCurr->isDebug  = _G.debugLine;
220
221     addpCode2pBlock(pb,newpCodeCharP(lb));
222
223     va_end(ap);
224 }
225
226
227 void emitpLabel(int key)
228 {
229   addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
230 }
231
232 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
233 {
234
235   if(pcop)
236     addpCode2pBlock(pb,newpCode(poc,pcop));
237   else
238     DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
239 }
240
241 void emitpcodeNULLop(PIC_OPCODE poc)
242 {
243
244   addpCode2pBlock(pb,newpCode(poc,NULL));
245
246 }
247
248 /*-----------------------------------------------------------------*/
249 /* pic14_emitcode - writes the code into a file : for now it is simple    */
250 /*-----------------------------------------------------------------*/
251 void pic14_emitcode (char *inst,char *fmt, ...)
252 {
253     va_list ap;
254     char lb[INITIAL_INLINEASM];  
255     char *lbp = lb;
256
257     va_start(ap,fmt);   
258
259     if (inst && *inst) {
260         if (fmt && *fmt)
261             sprintf(lb,"%s\t",inst);
262         else
263             sprintf(lb,"%s",inst);
264         vsprintf(lb+(strlen(lb)),fmt,ap);
265     }  else
266         vsprintf(lb,fmt,ap);
267
268     while (isspace(*lbp)) lbp++;
269
270     if (lbp && *lbp) 
271         lineCurr = (lineCurr ?
272                     connectLine(lineCurr,newLineNode(lb)) :
273                     (lineHead = newLineNode(lb)));
274     lineCurr->isInline = _G.inLine;
275     lineCurr->isDebug  = _G.debugLine;
276
277     if(debug_verbose)
278       addpCode2pBlock(pb,newpCodeCharP(lb));
279
280     va_end(ap);
281 }
282
283
284 /*-----------------------------------------------------------------*/
285 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
286 /*-----------------------------------------------------------------*/
287 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
288 {
289     bool r0iu = FALSE , r1iu = FALSE;
290     bool r0ou = FALSE , r1ou = FALSE;
291
292     /* the logic: if r0 & r1 used in the instruction
293     then we are in trouble otherwise */
294
295     /* first check if r0 & r1 are used by this
296     instruction, in which case we are in trouble */
297     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
298         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
299     {
300         goto endOfWorld;      
301     }
302
303     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
304     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
305
306     /* if no usage of r0 then return it */
307     if (!r0iu && !r0ou) {
308         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
309         (*aopp)->type = AOP_R0;
310         
311         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
312     }
313
314     /* if no usage of r1 then return it */
315     if (!r1iu && !r1ou) {
316         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
317         (*aopp)->type = AOP_R1;
318
319         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
320     }    
321
322     /* now we know they both have usage */
323     /* if r0 not used in this instruction */
324     if (!r0iu) {
325         /* push it if not already pushed */
326         if (!_G.r0Pushed) {
327           //pic14_emitcode ("push","%s",
328           //          pic14_regWithIdx(R0_IDX)->dname);
329             _G.r0Pushed++ ;
330         }
331         
332         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
333         (*aopp)->type = AOP_R0;
334
335         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
336     }
337
338     /* if r1 not used then */
339
340     if (!r1iu) {
341         /* push it if not already pushed */
342         if (!_G.r1Pushed) {
343           //pic14_emitcode ("push","%s",
344           //          pic14_regWithIdx(R1_IDX)->dname);
345             _G.r1Pushed++ ;
346         }
347         
348         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
349         (*aopp)->type = AOP_R1;
350         return pic14_regWithIdx(R1_IDX);
351     }
352
353 endOfWorld :
354     /* I said end of world but not quite end of world yet */
355     /* if this is a result then we can push it on the stack*/
356     if (result) {
357         (*aopp)->type = AOP_STK;    
358         return NULL;
359     }
360
361     /* other wise this is true end of the world */
362     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
363            "getFreePtr should never reach here");
364     exit(0);
365 }
366
367 /*-----------------------------------------------------------------*/
368 /* newAsmop - creates a new asmOp                                  */
369 /*-----------------------------------------------------------------*/
370 asmop *newAsmop (short type)
371 {
372     asmop *aop;
373
374     aop = Safe_calloc(1,sizeof(asmop));
375     aop->type = type;
376     return aop;
377 }
378
379 static void genSetDPTR(int n)
380 {
381     if (!n)
382     {
383         pic14_emitcode(";", "Select standard DPTR");
384         pic14_emitcode("mov", "dps, #0x00");
385     }
386     else
387     {
388         pic14_emitcode(";", "Select alternate DPTR");
389         pic14_emitcode("mov", "dps, #0x01");
390     }
391 }
392
393 /*-----------------------------------------------------------------*/
394 /* resolveIfx - converts an iCode ifx into a form more useful for  */
395 /*              generating code                                    */
396 /*-----------------------------------------------------------------*/
397 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
398 {
399   if(!resIfx) 
400     return;
401
402   DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
403
404   resIfx->condition = 1;    /* assume that the ifx is true */
405   resIfx->generated = 0;    /* indicate that the ifx has not been used */
406
407   if(!ifx) {
408     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
409     DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
410                         __FUNCTION__,__LINE__,resIfx->lbl->key);
411   } else {
412     if(IC_TRUE(ifx)) {
413       resIfx->lbl = IC_TRUE(ifx);
414     } else {
415       resIfx->lbl = IC_FALSE(ifx);
416       resIfx->condition = 0;
417     }
418     if(IC_TRUE(ifx)) 
419       DEBUGpic14_emitcode("; ***","ifx true is non-null");
420     if(IC_FALSE(ifx)) 
421       DEBUGpic14_emitcode("; ***","ifx false is non-null");
422   }
423
424   DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
425
426 }
427 /*-----------------------------------------------------------------*/
428 /* pointerCode - returns the code for a pointer type               */
429 /*-----------------------------------------------------------------*/
430 static int pointerCode (sym_link *etype)
431 {
432
433     return PTR_TYPE(SPEC_OCLS(etype));
434
435 }
436
437 /*-----------------------------------------------------------------*/
438 /* aopForSym - for a true symbol                                   */
439 /*-----------------------------------------------------------------*/
440 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
441 {
442     asmop *aop;
443     memmap *space= SPEC_OCLS(sym->etype);
444
445     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
446     /* if already has one */
447     if (sym->aop)
448         return sym->aop;
449
450     /* assign depending on the storage class */
451     /* if it is on the stack or indirectly addressable */
452     /* space we need to assign either r0 or r1 to it   */    
453     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
454         sym->aop = aop = newAsmop(0);
455         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
456         aop->size = getSize(sym->type);
457
458         /* now assign the address of the variable to 
459         the pointer register */
460         if (aop->type != AOP_STK) {
461
462             if (sym->onStack) {
463                     if ( _G.accInUse )
464                         pic14_emitcode("push","acc");
465
466                     pic14_emitcode("mov","a,_bp");
467                     pic14_emitcode("add","a,#0x%02x",
468                              ((sym->stack < 0) ?
469                               ((char)(sym->stack - _G.nRegsSaved )) :
470                               ((char)sym->stack)) & 0xff);
471                     pic14_emitcode("mov","%s,a",
472                              aop->aopu.aop_ptr->name);
473
474                     if ( _G.accInUse )
475                         pic14_emitcode("pop","acc");
476             } else
477                 pic14_emitcode("mov","%s,#%s",
478                          aop->aopu.aop_ptr->name,
479                          sym->rname);
480             aop->paged = space->paged;
481         } else
482             aop->aopu.aop_stk = sym->stack;
483         return aop;
484     }
485     
486     if (sym->onStack && options.stack10bit)
487     {
488         /* It's on the 10 bit stack, which is located in
489          * far data space.
490          */
491          
492       //DEBUGpic14_emitcode(";","%d",__LINE__);
493
494         if ( _G.accInUse )
495                 pic14_emitcode("push","acc");
496
497         pic14_emitcode("mov","a,_bp");
498         pic14_emitcode("add","a,#0x%02x",
499                  ((sym->stack < 0) ?
500                    ((char)(sym->stack - _G.nRegsSaved )) :
501                    ((char)sym->stack)) & 0xff);
502         
503         genSetDPTR(1);
504         pic14_emitcode ("mov","dpx1,#0x40");
505         pic14_emitcode ("mov","dph1,#0x00");
506         pic14_emitcode ("mov","dpl1, a");
507         genSetDPTR(0);
508         
509         if ( _G.accInUse )
510             pic14_emitcode("pop","acc");
511             
512         sym->aop = aop = newAsmop(AOP_DPTR2);
513         aop->size = getSize(sym->type); 
514         return aop;
515     }
516
517     //DEBUGpic14_emitcode(";","%d",__LINE__);
518     /* if in bit space */
519     if (IN_BITSPACE(space)) {
520         sym->aop = aop = newAsmop (AOP_CRY);
521         aop->aopu.aop_dir = sym->rname ;
522         aop->size = getSize(sym->type);
523         //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
524         return aop;
525     }
526     /* if it is in direct space */
527     if (IN_DIRSPACE(space)) {
528         sym->aop = aop = newAsmop (AOP_DIR);
529         aop->aopu.aop_dir = sym->rname ;
530         aop->size = getSize(sym->type);
531         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
532         return aop;
533     }
534
535     /* special case for a function */
536     if (IS_FUNC(sym->type)) {   
537         sym->aop = aop = newAsmop(AOP_IMMD);    
538         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
539         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
540         strcpy(aop->aopu.aop_immd,sym->rname);
541         aop->size = FPTRSIZE; 
542         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
543         return aop;
544     }
545
546
547     /* only remaining is far space */
548     /* in which case DPTR gets the address */
549     sym->aop = aop = newAsmop(AOP_DPTR);
550     pic14_emitcode ("mov","dptr,#%s", sym->rname);
551     aop->size = getSize(sym->type);
552
553     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
554     /* if it is in code space */
555     if (IN_CODESPACE(space))
556         aop->code = 1;
557
558     return aop;     
559 }
560
561 /*-----------------------------------------------------------------*/
562 /* aopForRemat - rematerialzes an object                           */
563 /*-----------------------------------------------------------------*/
564 static asmop *aopForRemat (symbol *sym)
565 {
566     iCode *ic = sym->rematiCode;
567     //X asmop *aop = newAsmop(AOP_IMMD);
568     asmop *aop = newAsmop(AOP_PCODE);
569     int val = 0;
570     int offset = 0;
571
572     DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
573
574     for (;;) {
575       if (ic->op == '+') {
576         val += (int) operandLitValue(IC_RIGHT(ic));
577       } else if (ic->op == '-') {
578         val -= (int) operandLitValue(IC_RIGHT(ic));
579       } else
580             break;
581         
582         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
583     }
584 /* X
585     if (val) {
586         sprintf(buffer,"(%s %c 0x%04x)",
587                 OP_SYMBOL(IC_LEFT(ic))->rname, 
588                 val >= 0 ? '+' : '-',
589                 abs(val) & 0xffff);
590         fprintf(stderr,"hmmm %s\n",buffer);
591     } else
592         strcpy(buffer,OP_SYMBOL(IC_LEFT(ic))->rname);
593 */
594     //ic = sym->rematiCode;
595     offset = OP_SYMBOL(IC_LEFT(ic))->offset;
596     aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,val);
597     DEBUGpic14_emitcode(";"," rname %s, val %d ",OP_SYMBOL(IC_LEFT(ic))->rname,val);
598     //X aop->aopu.aop_immd = Safe_calloc(1,strlen(buffer)+1);
599     //X strcpy(aop->aopu.aop_immd,buffer);    
600
601     allocDirReg (IC_LEFT(ic));
602
603     return aop;        
604 }
605
606 int aopIdx (asmop *aop, int offset)
607 {
608   if(!aop)
609     return -1;
610
611   if(aop->type !=  AOP_REG)
612     return -2;
613         
614   return aop->aopu.aop_reg[offset]->rIdx;
615
616 }
617 /*-----------------------------------------------------------------*/
618 /* regsInCommon - two operands have some registers in common       */
619 /*-----------------------------------------------------------------*/
620 static bool regsInCommon (operand *op1, operand *op2)
621 {
622     symbol *sym1, *sym2;
623     int i;
624
625     /* if they have registers in common */
626     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
627         return FALSE ;
628
629     sym1 = OP_SYMBOL(op1);
630     sym2 = OP_SYMBOL(op2);
631
632     if (sym1->nRegs == 0 || sym2->nRegs == 0)
633         return FALSE ;
634
635     for (i = 0 ; i < sym1->nRegs ; i++) {
636         int j;
637         if (!sym1->regs[i])
638             continue ;
639
640         for (j = 0 ; j < sym2->nRegs ;j++ ) {
641             if (!sym2->regs[j])
642                 continue ;
643
644             if (sym2->regs[j] == sym1->regs[i])
645                 return TRUE ;
646         }
647     }
648
649     return FALSE ;
650 }
651
652 /*-----------------------------------------------------------------*/
653 /* operandsEqu - equivalent                                        */
654 /*-----------------------------------------------------------------*/
655 static bool operandsEqu ( operand *op1, operand *op2)
656 {
657     symbol *sym1, *sym2;
658
659     /* if they not symbols */
660     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
661         return FALSE;
662
663     sym1 = OP_SYMBOL(op1);
664     sym2 = OP_SYMBOL(op2);
665
666     /* if both are itemps & one is spilt
667        and the other is not then false */
668     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
669         sym1->isspilt != sym2->isspilt )
670         return FALSE ;
671
672     /* if they are the same */
673     if (sym1 == sym2)
674         return TRUE ;
675
676     if (strcmp(sym1->rname,sym2->rname) == 0)
677         return TRUE;
678
679
680     /* if left is a tmp & right is not */
681     if (IS_ITEMP(op1)  && 
682         !IS_ITEMP(op2) &&
683         sym1->isspilt  &&
684         (sym1->usl.spillLoc == sym2))
685         return TRUE;
686
687     if (IS_ITEMP(op2)  && 
688         !IS_ITEMP(op1) &&
689         sym2->isspilt  &&
690         sym1->level > 0 &&
691         (sym2->usl.spillLoc == sym1))
692         return TRUE ;
693
694     return FALSE ;
695 }
696
697 /*-----------------------------------------------------------------*/
698 /* pic14_sameRegs - two asmops have the same registers                   */
699 /*-----------------------------------------------------------------*/
700 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
701 {
702     int i;
703
704     if (aop1 == aop2)
705         return TRUE ;
706
707     if (aop1->type != AOP_REG ||
708         aop2->type != AOP_REG )
709         return FALSE ;
710
711     if (aop1->size != aop2->size )
712         return FALSE ;
713
714     for (i = 0 ; i < aop1->size ; i++ )
715         if (aop1->aopu.aop_reg[i] !=
716             aop2->aopu.aop_reg[i] )
717             return FALSE ;
718
719     return TRUE ;
720 }
721
722 /*-----------------------------------------------------------------*/
723 /* aopOp - allocates an asmop for an operand  :                    */
724 /*-----------------------------------------------------------------*/
725 void aopOp (operand *op, iCode *ic, bool result)
726 {
727     asmop *aop;
728     symbol *sym;
729     int i;
730
731     if (!op)
732         return ;
733
734     //    DEBUGpic14_emitcode(";","%d",__LINE__);
735     /* if this a literal */
736     if (IS_OP_LITERAL(op)) {
737         op->aop = aop = newAsmop(AOP_LIT);
738         aop->aopu.aop_lit = op->operand.valOperand;
739         aop->size = getSize(operandType(op));
740         return;
741     }
742
743     {
744       sym_link *type = operandType(op);
745       if(IS_PTR_CONST(type))
746         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
747     }
748
749     /* if already has a asmop then continue */
750     if (op->aop)
751         return ;
752
753     /* if the underlying symbol has a aop */
754     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
755       DEBUGpic14_emitcode(";","%d",__LINE__);
756         op->aop = OP_SYMBOL(op)->aop;
757         return;
758     }
759
760     /* if this is a true symbol */
761     if (IS_TRUE_SYMOP(op)) {    
762       //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
763       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
764       return ;
765     }
766
767     /* this is a temporary : this has
768     only four choices :
769     a) register
770     b) spillocation
771     c) rematerialize 
772     d) conditional   
773     e) can be a return use only */
774
775     sym = OP_SYMBOL(op);
776
777
778     /* if the type is a conditional */
779     if (sym->regType == REG_CND) {
780         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
781         aop->size = 0;
782         return;
783     }
784
785     /* if it is spilt then two situations
786     a) is rematerialize 
787     b) has a spill location */
788     if (sym->isspilt || sym->nRegs == 0) {
789
790       DEBUGpic14_emitcode(";","%d",__LINE__);
791         /* rematerialize it NOW */
792         if (sym->remat) {
793             sym->aop = op->aop = aop =
794                                       aopForRemat (sym);
795             aop->size = getSize(sym->type);
796             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
797             return;
798         }
799
800         if (sym->accuse) {
801             int i;
802             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
803             aop->size = getSize(sym->type);
804             for ( i = 0 ; i < 2 ; i++ )
805                 aop->aopu.aop_str[i] = accUse[i];
806             DEBUGpic14_emitcode(";","%d",__LINE__);
807             return;  
808         }
809
810         if (sym->ruonly ) {
811             unsigned i;
812             aop = op->aop = sym->aop = newAsmop(AOP_STR);
813             aop->size = getSize(sym->type);
814             for ( i = 0 ; i < fReturnSizePic ; i++ )
815               aop->aopu.aop_str[i] = fReturn[i];
816             DEBUGpic14_emitcode(";","%d",__LINE__);
817             return;
818         }
819
820         /* else spill location  */
821         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
822             /* force a new aop if sizes differ */
823             sym->usl.spillLoc->aop = NULL;
824         }
825         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
826                             __FUNCTION__,__LINE__,
827                             sym->usl.spillLoc->rname,
828                             sym->rname, sym->usl.spillLoc->offset);
829         // X sym->aop = op->aop = aop = aopForSym(ic,sym->usl.spillLoc,result);
830         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
831         aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,sym->usl.spillLoc->offset);
832         //allocDirReg (IC_LEFT(ic));
833         aop->size = getSize(sym->type);
834
835         return;
836     }
837
838     {
839       sym_link *type = operandType(op);
840       if(IS_PTR_CONST(type)) 
841         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
842     }
843
844     /* must be in a register */
845     sym->aop = op->aop = aop = newAsmop(AOP_REG);
846     aop->size = sym->nRegs;
847     for ( i = 0 ; i < sym->nRegs ;i++)
848         aop->aopu.aop_reg[i] = sym->regs[i];
849 }
850
851 /*-----------------------------------------------------------------*/
852 /* freeAsmop - free up the asmop given to an operand               */
853 /*----------------------------------------------------------------*/
854 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
855 {   
856     asmop *aop ;
857
858     if (!op)
859         aop = aaop;
860     else 
861         aop = op->aop;
862
863     if (!aop)
864         return ;
865
866     if (aop->freed)
867         goto dealloc; 
868
869     aop->freed = 1;
870
871     /* depending on the asmop type only three cases need work AOP_RO
872        , AOP_R1 && AOP_STK */
873 #if 0
874     switch (aop->type) {
875         case AOP_R0 :
876             if (_G.r0Pushed ) {
877                 if (pop) {
878                     pic14_emitcode ("pop","ar0");     
879                     _G.r0Pushed--;
880                 }
881             }
882             bitVectUnSetBit(ic->rUsed,R0_IDX);
883             break;
884
885         case AOP_R1 :
886             if (_G.r1Pushed ) {
887                 if (pop) {
888                     pic14_emitcode ("pop","ar1");
889                     _G.r1Pushed--;
890                 }
891             }
892             bitVectUnSetBit(ic->rUsed,R1_IDX);          
893             break;
894
895         case AOP_STK :
896         {
897             int sz = aop->size;    
898             int stk = aop->aopu.aop_stk + aop->size;
899             bitVectUnSetBit(ic->rUsed,R0_IDX);
900             bitVectUnSetBit(ic->rUsed,R1_IDX);          
901
902             getFreePtr(ic,&aop,FALSE);
903             
904             if (options.stack10bit)
905             {
906                 /* I'm not sure what to do here yet... */
907                 /* #STUB */
908                 fprintf(stderr, 
909                         "*** Warning: probably generating bad code for "
910                         "10 bit stack mode.\n");
911             }
912             
913             if (stk) {
914                 pic14_emitcode ("mov","a,_bp");
915                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
916                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
917             } else {
918                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
919             }
920
921             while (sz--) {
922                 pic14_emitcode("pop","acc");
923                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
924                 if (!sz) break;
925                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
926             }
927             op->aop = aop;
928             freeAsmop(op,NULL,ic,TRUE);
929             if (_G.r0Pushed) {
930                 pic14_emitcode("pop","ar0");
931                 _G.r0Pushed--;
932             }
933
934             if (_G.r1Pushed) {
935                 pic14_emitcode("pop","ar1");
936                 _G.r1Pushed--;
937             }       
938         }
939     }
940 #endif
941
942 dealloc:
943     /* all other cases just dealloc */
944     if (op ) {
945         op->aop = NULL;
946         if (IS_SYMOP(op)) {
947             OP_SYMBOL(op)->aop = NULL;    
948             /* if the symbol has a spill */
949             if (SPIL_LOC(op))
950                 SPIL_LOC(op)->aop = NULL;
951         }
952     }
953 }
954
955 /*-----------------------------------------------------------------*/
956 /* aopGet - for fetching value of the aop                          */
957 /*-----------------------------------------------------------------*/
958 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
959 {
960     char *s = buffer ;
961     char *rs;
962
963     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
964     /* offset is greater than
965     size then zero */
966     if (offset > (aop->size - 1) &&
967         aop->type != AOP_LIT)
968         return zero;
969
970     /* depending on type */
971     switch (aop->type) {
972         
973     case AOP_R0:
974     case AOP_R1:
975         DEBUGpic14_emitcode(";","%d",__LINE__);
976         /* if we need to increment it */       
977         while (offset > aop->coff) {        
978             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
979             aop->coff++;
980         }
981         
982         while (offset < aop->coff) {
983             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
984             aop->coff--;
985         }
986         
987         aop->coff = offset ;
988         if (aop->paged) {
989             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
990             return (dname ? "acc" : "a");
991         }       
992         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
993         rs = Safe_calloc(1,strlen(s)+1);
994         strcpy(rs,s);   
995         return rs;
996         
997     case AOP_DPTR:
998     case AOP_DPTR2:
999         DEBUGpic14_emitcode(";","%d",__LINE__);
1000     if (aop->type == AOP_DPTR2)
1001     {
1002         genSetDPTR(1);
1003     }
1004     
1005         while (offset > aop->coff) {
1006             pic14_emitcode ("inc","dptr");
1007             aop->coff++;
1008         }
1009         
1010         while (offset < aop->coff) {        
1011             pic14_emitcode("lcall","__decdptr");
1012             aop->coff--;
1013         }
1014         
1015         aop->coff = offset;
1016         if (aop->code) {
1017             pic14_emitcode("clr","a");
1018             pic14_emitcode("movc","a,@a+dptr");
1019         }
1020     else {
1021             pic14_emitcode("movx","a,@dptr");
1022     }
1023             
1024     if (aop->type == AOP_DPTR2)
1025     {
1026         genSetDPTR(0);
1027     }
1028             
1029     return (dname ? "acc" : "a");
1030         
1031         
1032     case AOP_IMMD:
1033         if (bit16) 
1034             sprintf (s,"%s",aop->aopu.aop_immd);
1035         else
1036             if (offset) 
1037                 sprintf(s,"(%s >> %d)",
1038                         aop->aopu.aop_immd,
1039                         offset*8);
1040             else
1041                 sprintf(s,"%s",
1042                         aop->aopu.aop_immd);
1043         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1044         rs = Safe_calloc(1,strlen(s)+1);
1045         strcpy(rs,s);   
1046         return rs;
1047         
1048     case AOP_DIR:
1049       if (offset) {
1050         sprintf(s,"(%s + %d)",
1051                 aop->aopu.aop_dir,
1052                 offset);
1053         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1054       } else
1055             sprintf(s,"%s",aop->aopu.aop_dir);
1056         rs = Safe_calloc(1,strlen(s)+1);
1057         strcpy(rs,s);   
1058         return rs;
1059         
1060     case AOP_REG:
1061       //if (dname) 
1062       //    return aop->aopu.aop_reg[offset]->dname;
1063       //else
1064             return aop->aopu.aop_reg[offset]->name;
1065         
1066     case AOP_CRY:
1067       //pic14_emitcode(";","%d",__LINE__);
1068       return aop->aopu.aop_dir;
1069         
1070     case AOP_ACC:
1071         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1072         return "AOP_accumulator_bug";
1073
1074     case AOP_LIT:
1075         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1076         rs = Safe_calloc(1,strlen(s)+1);
1077         strcpy(rs,s);   
1078         return rs;
1079         
1080     case AOP_STR:
1081         DEBUGpic14_emitcode(";","%d",__LINE__);
1082         aop->coff = offset ;
1083         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1084             dname)
1085             return "acc";
1086         
1087         return aop->aopu.aop_str[offset];
1088         
1089     case AOP_PCODE:
1090       {
1091         pCodeOp *pcop = aop->aopu.pcop;
1092         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE",__LINE__);
1093         if(pcop->name) {
1094           DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1095           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1096           sprintf(s,"%s", pcop->name);
1097         } else
1098           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1099
1100       }
1101       rs = Safe_calloc(1,strlen(s)+1);
1102       strcpy(rs,s);   
1103       return rs;
1104
1105     }
1106
1107     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1108            "aopget got unsupported aop->type");
1109     exit(0);
1110 }
1111
1112
1113 /*-----------------------------------------------------------------*/
1114 /* popGetTempReg - create a new temporary pCodeOp                  */
1115 /*-----------------------------------------------------------------*/
1116 pCodeOp *popGetTempReg(void)
1117 {
1118
1119   pCodeOp *pcop;
1120
1121   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1122   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1123     PCOR(pcop)->r->wasUsed=1;
1124     PCOR(pcop)->r->isFree=0;
1125   }
1126
1127   return pcop;
1128 }
1129
1130 /*-----------------------------------------------------------------*/
1131 /* popGetTempReg - create a new temporary pCodeOp                  */
1132 /*-----------------------------------------------------------------*/
1133 void popReleaseTempReg(pCodeOp *pcop)
1134 {
1135
1136   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1137     PCOR(pcop)->r->isFree = 1;
1138
1139 }
1140 /*-----------------------------------------------------------------*/
1141 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1142 /*-----------------------------------------------------------------*/
1143 pCodeOp *popGetLabel(unsigned int key)
1144 {
1145
1146   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1147
1148   if(key>max_key)
1149     max_key = key;
1150
1151   return newpCodeOpLabel(NULL,key+100+labelOffset);
1152 }
1153
1154 /*-----------------------------------------------------------------*/
1155 /* popCopyReg - copy a pcode operator                              */
1156 /*-----------------------------------------------------------------*/
1157 pCodeOp *popCopyReg(pCodeOpReg *pc)
1158 {
1159   pCodeOpReg *pcor;
1160
1161   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1162   pcor->pcop.type = pc->pcop.type;
1163   if(pc->pcop.name) {
1164     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1165       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1166   } else
1167     pcor->pcop.name = NULL;
1168
1169   pcor->r = pc->r;
1170   pcor->rIdx = pc->rIdx;
1171   pcor->r->wasUsed=1;
1172
1173   //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1174
1175   return PCOP(pcor);
1176 }
1177 /*-----------------------------------------------------------------*/
1178 /* popGet - asm operator to pcode operator conversion              */
1179 /*-----------------------------------------------------------------*/
1180 pCodeOp *popGetLit(unsigned int lit)
1181 {
1182
1183   return newpCodeOpLit(lit);
1184 }
1185
1186
1187 /*-----------------------------------------------------------------*/
1188 /* popGetImmd - asm operator to pcode immediate conversion         */
1189 /*-----------------------------------------------------------------*/
1190 pCodeOp *popGetImmd(char *name, unsigned int offset)
1191 {
1192
1193   return newpCodeOpImmd(name, offset);
1194 }
1195
1196
1197 /*-----------------------------------------------------------------*/
1198 /* popGet - asm operator to pcode operator conversion              */
1199 /*-----------------------------------------------------------------*/
1200 pCodeOp *popGetWithString(char *str)
1201 {
1202   pCodeOp *pcop;
1203
1204
1205   if(!str) {
1206     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1207     exit (1);
1208   }
1209
1210   pcop = newpCodeOp(str,PO_STR);
1211
1212   return pcop;
1213 }
1214
1215 pCodeOp *popRegFromString(char *str)
1216 {
1217
1218   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOp) );
1219   pcop->type = PO_DIR;
1220
1221   DEBUGpic14_emitcode(";","%d",__LINE__);
1222   pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1223
1224   return pcop;
1225 }
1226
1227 pCodeOp *popRegFromIdx(int rIdx)
1228 {
1229   pCodeOp *pcop;
1230
1231   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1232                        __FUNCTION__,__LINE__,rIdx);
1233
1234   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1235
1236   PCOR(pcop)->rIdx = rIdx;
1237   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1238   PCOR(pcop)->r->isFree = 0;
1239   PCOR(pcop)->r->wasUsed = 1;
1240
1241   pcop->type = PCOR(pcop)->r->pc_type;
1242
1243
1244   return pcop;
1245 }
1246 /*-----------------------------------------------------------------*/
1247 /* popGet - asm operator to pcode operator conversion              */
1248 /*-----------------------------------------------------------------*/
1249 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1250 {
1251   //char *s = buffer ;
1252     //char *rs;
1253
1254     pCodeOp *pcop;
1255
1256     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1257     /* offset is greater than
1258     size then zero */
1259
1260     if (offset > (aop->size - 1) &&
1261         aop->type != AOP_LIT)
1262       return NULL;  //zero;
1263
1264     /* depending on type */
1265     switch (aop->type) {
1266         
1267     case AOP_R0:
1268     case AOP_R1:
1269     case AOP_DPTR:
1270     case AOP_DPTR2:
1271     case AOP_ACC:
1272         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1273         return NULL;
1274         
1275     case AOP_IMMD:
1276       DEBUGpic14_emitcode(";","%d",__LINE__);
1277       return popGetImmd(aop->aopu.aop_immd,offset);
1278
1279     case AOP_DIR:
1280         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1281         pcop->type = PO_DIR;
1282
1283         /*
1284         if (offset)
1285             sprintf(s,"(%s + %d)",
1286                     aop->aopu.aop_dir,
1287                     offset);
1288         else
1289             sprintf(s,"%s",aop->aopu.aop_dir);
1290         pcop->name = Safe_calloc(1,strlen(s)+1);
1291         strcpy(pcop->name,s);   
1292         */
1293         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1294         strcpy(pcop->name,aop->aopu.aop_dir);   
1295         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1296         if(PCOR(pcop)->r == NULL) {
1297           fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1298           PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1299         } 
1300
1301       DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1302         PCOR(pcop)->instance = offset;
1303
1304         return pcop;
1305         
1306     case AOP_REG:
1307       {
1308         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1309
1310         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1311         PCOR(pcop)->rIdx = rIdx;
1312         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1313         PCOR(pcop)->instance = offset;
1314         pcop->type = PCOR(pcop)->r->pc_type;
1315         //rs = aop->aopu.aop_reg[offset]->name;
1316         //DEBUGpic14_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1317         return pcop;
1318       }
1319
1320     case AOP_CRY:
1321       pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1322       PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1323       if(PCOR(pcop)->r == NULL)
1324         fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1325       return pcop;
1326         
1327     case AOP_LIT:
1328       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1329
1330     case AOP_STR:
1331       DEBUGpic14_emitcode(";","%d",__LINE__);
1332       return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1333       /*
1334       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1335       PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1336       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1337       pcop->type = PCOR(pcop)->r->pc_type;
1338       pcop->name = PCOR(pcop)->r->name;
1339
1340       return pcop;
1341       */
1342
1343     case AOP_PCODE:
1344       DEBUGpic14_emitcode(";","popGet AOP_PCODE%d",__LINE__);
1345       return pCodeOpCopy(aop->aopu.pcop);
1346     }
1347
1348     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1349            "popGet got unsupported aop->type");
1350     exit(0);
1351 }
1352 /*-----------------------------------------------------------------*/
1353 /* aopPut - puts a string for a aop                                */
1354 /*-----------------------------------------------------------------*/
1355 void aopPut (asmop *aop, char *s, int offset)
1356 {
1357     char *d = buffer ;
1358     symbol *lbl ;
1359
1360     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1361
1362     if (aop->size && offset > ( aop->size - 1)) {
1363         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1364                "aopPut got offset > aop->size");
1365         exit(0);
1366     }
1367
1368     /* will assign value to value */
1369     /* depending on where it is ofcourse */
1370     switch (aop->type) {
1371     case AOP_DIR:
1372       if (offset) {
1373         sprintf(d,"(%s + %d)",
1374                 aop->aopu.aop_dir,offset);
1375         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1376
1377       } else
1378             sprintf(d,"%s",aop->aopu.aop_dir);
1379         
1380         if (strcmp(d,s)) {
1381           DEBUGpic14_emitcode(";","%d",__LINE__);
1382           if(strcmp(s,"W"))
1383             pic14_emitcode("movf","%s,w",s);
1384           pic14_emitcode("movwf","%s",d);
1385
1386           if(strcmp(s,"W")) {
1387             pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1388             if(offset >= aop->size) {
1389               emitpcode(POC_CLRF,popGet(aop,offset));
1390               break;
1391             } else
1392               emitpcode(POC_MOVLW,popGetImmd(s,offset));
1393           }
1394
1395           emitpcode(POC_MOVWF,popGet(aop,offset));
1396
1397
1398         }
1399         break;
1400         
1401     case AOP_REG:
1402       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1403         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1404           /*
1405             if (*s == '@'           ||
1406                 strcmp(s,"r0") == 0 ||
1407                 strcmp(s,"r1") == 0 ||
1408                 strcmp(s,"r2") == 0 ||
1409                 strcmp(s,"r3") == 0 ||
1410                 strcmp(s,"r4") == 0 ||
1411                 strcmp(s,"r5") == 0 ||
1412                 strcmp(s,"r6") == 0 || 
1413                 strcmp(s,"r7") == 0 )
1414                 pic14_emitcode("mov","%s,%s  ; %d",
1415                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1416             else
1417           */
1418
1419           if(strcmp(s,"W"))
1420             pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1421
1422           pic14_emitcode("movwf","%s",
1423                    aop->aopu.aop_reg[offset]->name);
1424
1425           if(strcmp(s,"W")) {
1426             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1427             pcop->type = PO_GPR_REGISTER;
1428
1429             PCOR(pcop)->rIdx = -1;
1430             PCOR(pcop)->r = NULL;
1431
1432             DEBUGpic14_emitcode(";","%d",__LINE__);
1433             pcop->name = Safe_strdup(s);
1434             emitpcode(POC_MOVFW,pcop);
1435           }
1436           emitpcode(POC_MOVWF,popGet(aop,offset));
1437
1438         }
1439         break;
1440         
1441     case AOP_DPTR:
1442     case AOP_DPTR2:
1443     
1444     if (aop->type == AOP_DPTR2)
1445     {
1446         genSetDPTR(1);
1447     }
1448     
1449         if (aop->code) {
1450             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1451                    "aopPut writting to code space");
1452             exit(0);
1453         }
1454         
1455         while (offset > aop->coff) {
1456             aop->coff++;
1457             pic14_emitcode ("inc","dptr");
1458         }
1459         
1460         while (offset < aop->coff) {
1461             aop->coff-- ;
1462             pic14_emitcode("lcall","__decdptr");
1463         }
1464         
1465         aop->coff = offset;
1466         
1467         /* if not in accumulater */
1468         MOVA(s);        
1469         
1470         pic14_emitcode ("movx","@dptr,a");
1471         
1472     if (aop->type == AOP_DPTR2)
1473     {
1474         genSetDPTR(0);
1475     }
1476         break;
1477         
1478     case AOP_R0:
1479     case AOP_R1:
1480         while (offset > aop->coff) {
1481             aop->coff++;
1482             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1483         }
1484         while (offset < aop->coff) {
1485             aop->coff-- ;
1486             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1487         }
1488         aop->coff = offset;
1489         
1490         if (aop->paged) {
1491             MOVA(s);           
1492             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1493             
1494         } else
1495             if (*s == '@') {
1496                 MOVA(s);
1497                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1498             } else
1499                 if (strcmp(s,"r0") == 0 ||
1500                     strcmp(s,"r1") == 0 ||
1501                     strcmp(s,"r2") == 0 ||
1502                     strcmp(s,"r3") == 0 ||
1503                     strcmp(s,"r4") == 0 ||
1504                     strcmp(s,"r5") == 0 ||
1505                     strcmp(s,"r6") == 0 || 
1506                     strcmp(s,"r7") == 0 ) {
1507                     char buffer[10];
1508                     sprintf(buffer,"a%s",s);
1509                     pic14_emitcode("mov","@%s,%s",
1510                              aop->aopu.aop_ptr->name,buffer);
1511                 } else
1512                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1513         
1514         break;
1515         
1516     case AOP_STK:
1517         if (strcmp(s,"a") == 0)
1518             pic14_emitcode("push","acc");
1519         else
1520             pic14_emitcode("push","%s",s);
1521         
1522         break;
1523         
1524     case AOP_CRY:
1525         /* if bit variable */
1526         if (!aop->aopu.aop_dir) {
1527             pic14_emitcode("clr","a");
1528             pic14_emitcode("rlc","a");
1529         } else {
1530             if (s == zero) 
1531                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1532             else
1533                 if (s == one)
1534                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1535                 else
1536                     if (!strcmp(s,"c"))
1537                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1538                     else {
1539                         lbl = newiTempLabel(NULL);
1540                         
1541                         if (strcmp(s,"a")) {
1542                             MOVA(s);
1543                         }
1544                         pic14_emitcode("clr","c");
1545                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1546                         pic14_emitcode("cpl","c");
1547                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1548                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1549                     }
1550         }
1551         break;
1552         
1553     case AOP_STR:
1554         aop->coff = offset;
1555         if (strcmp(aop->aopu.aop_str[offset],s))
1556             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1557         break;
1558         
1559     case AOP_ACC:
1560         aop->coff = offset;
1561         if (!offset && (strcmp(s,"acc") == 0))
1562             break;
1563         
1564         if (strcmp(aop->aopu.aop_str[offset],s))
1565             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1566         break;
1567
1568     default :
1569         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1570                "aopPut got unsupported aop->type");
1571         exit(0);    
1572     }    
1573
1574 }
1575
1576 /*-----------------------------------------------------------------*/
1577 /* reAdjustPreg - points a register back to where it should        */
1578 /*-----------------------------------------------------------------*/
1579 static void reAdjustPreg (asmop *aop)
1580 {
1581     int size ;
1582
1583     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1584     aop->coff = 0;
1585     if ((size = aop->size) <= 1)
1586         return ;
1587     size-- ;
1588     switch (aop->type) {
1589         case AOP_R0 :
1590         case AOP_R1 :
1591             while (size--)
1592                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1593             break;          
1594         case AOP_DPTR :
1595         case AOP_DPTR2:
1596             if (aop->type == AOP_DPTR2)
1597             {
1598                 genSetDPTR(1);
1599             } 
1600             while (size--)
1601             {
1602                 pic14_emitcode("lcall","__decdptr");
1603             }
1604                 
1605             if (aop->type == AOP_DPTR2)
1606             {
1607                 genSetDPTR(0);
1608             }                
1609             break;  
1610
1611     }   
1612
1613 }
1614
1615 /*-----------------------------------------------------------------*/
1616 /* genNotFloat - generates not for float operations              */
1617 /*-----------------------------------------------------------------*/
1618 static void genNotFloat (operand *op, operand *res)
1619 {
1620     int size, offset;
1621     char *l;
1622     symbol *tlbl ;
1623
1624     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1625     /* we will put 127 in the first byte of 
1626     the result */
1627     aopPut(AOP(res),"#127",0);
1628     size = AOP_SIZE(op) - 1;
1629     offset = 1;
1630
1631     l = aopGet(op->aop,offset++,FALSE,FALSE);
1632     MOVA(l);    
1633
1634     while(size--) {
1635         pic14_emitcode("orl","a,%s",
1636                  aopGet(op->aop,
1637                         offset++,FALSE,FALSE));
1638     }
1639     tlbl = newiTempLabel(NULL);
1640
1641     tlbl = newiTempLabel(NULL);
1642     aopPut(res->aop,one,1);
1643     pic14_emitcode("jz","%05d_DS_",(tlbl->key+100));
1644     aopPut(res->aop,zero,1);
1645     pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
1646
1647     size = res->aop->size - 2;
1648     offset = 2;    
1649     /* put zeros in the rest */
1650     while (size--) 
1651         aopPut(res->aop,zero,offset++);
1652 }
1653
1654 #if 0
1655 /*-----------------------------------------------------------------*/
1656 /* opIsGptr: returns non-zero if the passed operand is             */   
1657 /* a generic pointer type.                                         */
1658 /*-----------------------------------------------------------------*/ 
1659 static int opIsGptr(operand *op)
1660 {
1661     sym_link *type = operandType(op);
1662     
1663     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1664     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1665     {
1666         return 1;
1667     }
1668     return 0;        
1669 }
1670 #endif
1671
1672 /*-----------------------------------------------------------------*/
1673 /* pic14_getDataSize - get the operand data size                         */
1674 /*-----------------------------------------------------------------*/
1675 int pic14_getDataSize(operand *op)
1676 {
1677     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1678
1679
1680     return AOP_SIZE(op);
1681
1682     // tsd- in the pic port, the genptr size is 1, so this code here
1683     // fails. ( in the 8051 port, the size was 4).
1684 #if 0
1685     int size;
1686     size = AOP_SIZE(op);
1687     if (size == GPTRSIZE)
1688     {
1689         sym_link *type = operandType(op);
1690         if (IS_GENPTR(type))
1691         {
1692             /* generic pointer; arithmetic operations
1693              * should ignore the high byte (pointer type).
1694              */
1695             size--;
1696     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1697         }
1698     }
1699     return size;
1700 #endif
1701 }
1702
1703 /*-----------------------------------------------------------------*/
1704 /* pic14_outAcc - output Acc                                             */
1705 /*-----------------------------------------------------------------*/
1706 void pic14_outAcc(operand *result)
1707 {
1708   int size,offset;
1709   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1710   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1711
1712
1713   size = pic14_getDataSize(result);
1714   if(size){
1715     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1716     size--;
1717     offset = 1;
1718     /* unsigned or positive */
1719     while(size--)
1720       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1721   }
1722
1723 }
1724
1725 /*-----------------------------------------------------------------*/
1726 /* pic14_outBitC - output a bit C                                        */
1727 /*-----------------------------------------------------------------*/
1728 void pic14_outBitC(operand *result)
1729 {
1730
1731     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1732     /* if the result is bit */
1733     if (AOP_TYPE(result) == AOP_CRY) 
1734         aopPut(AOP(result),"c",0);
1735     else {
1736         pic14_emitcode("clr","a  ; %d", __LINE__);
1737         pic14_emitcode("rlc","a");
1738         pic14_outAcc(result);
1739     }
1740 }
1741
1742 /*-----------------------------------------------------------------*/
1743 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1744 /*-----------------------------------------------------------------*/
1745 void pic14_toBoolean(operand *oper)
1746 {
1747     int size = AOP_SIZE(oper) - 1;
1748     int offset = 1;
1749
1750     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1751
1752     if ( AOP_TYPE(oper) != AOP_ACC) {
1753       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1754     }
1755     while (size--) {
1756       emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1757     }
1758 }
1759
1760
1761 /*-----------------------------------------------------------------*/
1762 /* genNot - generate code for ! operation                          */
1763 /*-----------------------------------------------------------------*/
1764 static void genNot (iCode *ic)
1765 {
1766   symbol *tlbl;
1767   sym_link *optype = operandType(IC_LEFT(ic));
1768   int size;
1769
1770   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1771   /* assign asmOps to operand & result */
1772   aopOp (IC_LEFT(ic),ic,FALSE);
1773   aopOp (IC_RESULT(ic),ic,TRUE);
1774
1775   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1776   /* if in bit space then a special case */
1777   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1778     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1779       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1780       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1781     } else {
1782       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1783       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1784       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1785     }
1786     goto release;
1787   }
1788
1789   /* if type float then do float */
1790   if (IS_FLOAT(optype)) {
1791     genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1792     goto release;
1793   }
1794
1795   size = AOP_SIZE(IC_RESULT(ic));
1796   if(size == 1) {
1797     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1798     emitpcode(POC_ANDLW,popGetLit(1));
1799     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1800     goto release;
1801   }
1802   pic14_toBoolean(IC_LEFT(ic));
1803
1804   tlbl = newiTempLabel(NULL);
1805   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1806   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1807   pic14_outBitC(IC_RESULT(ic));
1808
1809  release:    
1810   /* release the aops */
1811   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1812   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1813 }
1814
1815
1816 /*-----------------------------------------------------------------*/
1817 /* genCpl - generate code for complement                           */
1818 /*-----------------------------------------------------------------*/
1819 static void genCpl (iCode *ic)
1820 {
1821     int offset = 0;
1822     int size ;
1823
1824
1825     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1826     /* assign asmOps to operand & result */
1827     aopOp (IC_LEFT(ic),ic,FALSE);
1828     aopOp (IC_RESULT(ic),ic,TRUE);
1829
1830     /* if both are in bit space then 
1831     a special case */
1832     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1833         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1834
1835         pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1836         pic14_emitcode("cpl","c"); 
1837         pic14_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1838         goto release; 
1839     } 
1840
1841     size = AOP_SIZE(IC_RESULT(ic));
1842     while (size--) {
1843         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1844         MOVA(l);       
1845         pic14_emitcode("cpl","a");
1846         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1847     }
1848
1849
1850 release:
1851     /* release the aops */
1852     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1853     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1854 }
1855
1856 /*-----------------------------------------------------------------*/
1857 /* genUminusFloat - unary minus for floating points                */
1858 /*-----------------------------------------------------------------*/
1859 static void genUminusFloat(operand *op,operand *result)
1860 {
1861     int size ,offset =0 ;
1862     char *l;
1863
1864     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1865     /* for this we just need to flip the 
1866     first it then copy the rest in place */
1867     size = AOP_SIZE(op) - 1;
1868     l = aopGet(AOP(op),3,FALSE,FALSE);
1869
1870     MOVA(l);    
1871
1872     pic14_emitcode("cpl","acc.7");
1873     aopPut(AOP(result),"a",3);    
1874
1875     while(size--) {
1876         aopPut(AOP(result),
1877                aopGet(AOP(op),offset,FALSE,FALSE),
1878                offset);
1879         offset++;
1880     }          
1881 }
1882
1883 /*-----------------------------------------------------------------*/
1884 /* genUminus - unary minus code generation                         */
1885 /*-----------------------------------------------------------------*/
1886 static void genUminus (iCode *ic)
1887 {
1888   int size, i;
1889   sym_link *optype, *rtype;
1890
1891
1892   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1893   /* assign asmops */
1894   aopOp(IC_LEFT(ic),ic,FALSE);
1895   aopOp(IC_RESULT(ic),ic,TRUE);
1896
1897   /* if both in bit space then special
1898      case */
1899   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1900       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1901
1902     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1903     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1904     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1905
1906     goto release; 
1907   } 
1908
1909   optype = operandType(IC_LEFT(ic));
1910   rtype = operandType(IC_RESULT(ic));
1911
1912   /* if float then do float stuff */
1913   if (IS_FLOAT(optype)) {
1914     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1915     goto release;
1916   }
1917
1918   /* otherwise subtract from zero by taking the 2's complement */
1919   size = AOP_SIZE(IC_LEFT(ic));
1920
1921   for(i=0; i<size; i++) {
1922     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1923       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1924     else {
1925       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1926       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1927     }
1928   }
1929
1930   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1931   for(i=1; i<size; i++) {
1932     emitSKPNZ;
1933     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1934   }
1935
1936  release:
1937   /* release the aops */
1938   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1939   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1940 }
1941
1942 /*-----------------------------------------------------------------*/
1943 /* saveRegisters - will look for a call and save the registers     */
1944 /*-----------------------------------------------------------------*/
1945 static void saveRegisters(iCode *lic) 
1946 {
1947     int i;
1948     iCode *ic;
1949     bitVect *rsave;
1950     sym_link *dtype;
1951
1952     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1953     /* look for call */
1954     for (ic = lic ; ic ; ic = ic->next) 
1955         if (ic->op == CALL || ic->op == PCALL)
1956             break;
1957
1958     if (!ic) {
1959         fprintf(stderr,"found parameter push with no function call\n");
1960         return ;
1961     }
1962
1963     /* if the registers have been saved already then
1964     do nothing */
1965     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1966         return ;
1967
1968     /* find the registers in use at this time 
1969     and push them away to safety */
1970     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1971                           ic->rUsed);
1972
1973     ic->regsSaved = 1;
1974     if (options.useXstack) {
1975         if (bitVectBitValue(rsave,R0_IDX))
1976             pic14_emitcode("mov","b,r0");
1977         pic14_emitcode("mov","r0,%s",spname);
1978         for (i = 0 ; i < pic14_nRegs ; i++) {
1979             if (bitVectBitValue(rsave,i)) {
1980                 if (i == R0_IDX)
1981                     pic14_emitcode("mov","a,b");
1982                 else
1983                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
1984                 pic14_emitcode("movx","@r0,a");
1985                 pic14_emitcode("inc","r0");
1986             }
1987         }
1988         pic14_emitcode("mov","%s,r0",spname);
1989         if (bitVectBitValue(rsave,R0_IDX))
1990             pic14_emitcode("mov","r0,b");           
1991     }// else
1992     //for (i = 0 ; i < pic14_nRegs ; i++) {
1993     //    if (bitVectBitValue(rsave,i))
1994     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
1995     //}
1996
1997     dtype = operandType(IC_LEFT(ic));
1998     if (currFunc && dtype && 
1999         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2000         IFFUNC_ISISR(currFunc->type) &&
2001         !ic->bankSaved) 
2002
2003         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2004
2005 }
2006 /*-----------------------------------------------------------------*/
2007 /* unsaveRegisters - pop the pushed registers                      */
2008 /*-----------------------------------------------------------------*/
2009 static void unsaveRegisters (iCode *ic)
2010 {
2011     int i;
2012     bitVect *rsave;
2013
2014     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2015     /* find the registers in use at this time 
2016     and push them away to safety */
2017     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2018                           ic->rUsed);
2019     
2020     if (options.useXstack) {
2021         pic14_emitcode("mov","r0,%s",spname);   
2022         for (i =  pic14_nRegs ; i >= 0 ; i--) {
2023             if (bitVectBitValue(rsave,i)) {
2024                 pic14_emitcode("dec","r0");
2025                 pic14_emitcode("movx","a,@r0");
2026                 if (i == R0_IDX)
2027                     pic14_emitcode("mov","b,a");
2028                 else
2029                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2030             }       
2031
2032         }
2033         pic14_emitcode("mov","%s,r0",spname);
2034         if (bitVectBitValue(rsave,R0_IDX))
2035             pic14_emitcode("mov","r0,b");
2036     } //else
2037     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2038     //    if (bitVectBitValue(rsave,i))
2039     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2040     //}
2041
2042 }  
2043
2044
2045 /*-----------------------------------------------------------------*/
2046 /* pushSide -                                                      */
2047 /*-----------------------------------------------------------------*/
2048 static void pushSide(operand * oper, int size)
2049 {
2050 #if 0
2051         int offset = 0;
2052     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2053         while (size--) {
2054                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2055                 if (AOP_TYPE(oper) != AOP_REG &&
2056                     AOP_TYPE(oper) != AOP_DIR &&
2057                     strcmp(l,"a") ) {
2058                         pic14_emitcode("mov","a,%s",l);
2059                         pic14_emitcode("push","acc");
2060                 } else
2061                         pic14_emitcode("push","%s",l);
2062         }
2063 #endif
2064 }
2065
2066 /*-----------------------------------------------------------------*/
2067 /* assignResultValue -                                             */
2068 /*-----------------------------------------------------------------*/
2069 static void assignResultValue(operand * oper)
2070 {
2071   int size = AOP_SIZE(oper);
2072
2073   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2074
2075   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2076
2077   if(!GpsuedoStkPtr) {
2078     /* The last byte in the assignment is in W */
2079     size--;
2080     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2081     GpsuedoStkPtr++;
2082   }
2083
2084   while (size--) {
2085     emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
2086     GpsuedoStkPtr++;
2087     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2088   }
2089 }
2090
2091
2092 /*-----------------------------------------------------------------*/
2093 /* genIpush - genrate code for pushing this gets a little complex  */
2094 /*-----------------------------------------------------------------*/
2095 static void genIpush (iCode *ic)
2096 {
2097
2098   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2099 #if 0
2100     int size, offset = 0 ;
2101     char *l;
2102
2103
2104     /* if this is not a parm push : ie. it is spill push 
2105     and spill push is always done on the local stack */
2106     if (!ic->parmPush) {
2107
2108         /* and the item is spilt then do nothing */
2109         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2110             return ;
2111
2112         aopOp(IC_LEFT(ic),ic,FALSE);
2113         size = AOP_SIZE(IC_LEFT(ic));
2114         /* push it on the stack */
2115         while(size--) {
2116             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2117             if (*l == '#') {
2118                 MOVA(l);
2119                 l = "acc";
2120             }
2121             pic14_emitcode("push","%s",l);
2122         }
2123         return ;        
2124     }
2125
2126     /* this is a paramter push: in this case we call
2127     the routine to find the call and save those
2128     registers that need to be saved */   
2129     saveRegisters(ic);
2130
2131     /* then do the push */
2132     aopOp(IC_LEFT(ic),ic,FALSE);
2133
2134
2135         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2136     size = AOP_SIZE(IC_LEFT(ic));
2137
2138     while (size--) {
2139         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2140         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2141             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2142             strcmp(l,"a") ) {
2143             pic14_emitcode("mov","a,%s",l);
2144             pic14_emitcode("push","acc");
2145         } else
2146             pic14_emitcode("push","%s",l);
2147     }       
2148
2149     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2150 #endif
2151 }
2152
2153 /*-----------------------------------------------------------------*/
2154 /* genIpop - recover the registers: can happen only for spilling   */
2155 /*-----------------------------------------------------------------*/
2156 static void genIpop (iCode *ic)
2157 {
2158   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2159 #if 0
2160     int size,offset ;
2161
2162
2163     /* if the temp was not pushed then */
2164     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2165         return ;
2166
2167     aopOp(IC_LEFT(ic),ic,FALSE);
2168     size = AOP_SIZE(IC_LEFT(ic));
2169     offset = (size-1);
2170     while (size--) 
2171         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2172                                    FALSE,TRUE));
2173
2174     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2175 #endif
2176 }
2177
2178 /*-----------------------------------------------------------------*/
2179 /* unsaverbank - restores the resgister bank from stack            */
2180 /*-----------------------------------------------------------------*/
2181 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2182 {
2183   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2184 #if 0
2185     int i;
2186     asmop *aop ;
2187     regs *r = NULL;
2188
2189     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2190     if (popPsw) {
2191         if (options.useXstack) {
2192             aop = newAsmop(0);
2193             r = getFreePtr(ic,&aop,FALSE);
2194             
2195             
2196             pic14_emitcode("mov","%s,_spx",r->name);
2197             pic14_emitcode("movx","a,@%s",r->name);
2198             pic14_emitcode("mov","psw,a");
2199             pic14_emitcode("dec","%s",r->name);
2200             
2201         }else
2202             pic14_emitcode ("pop","psw");
2203     }
2204
2205     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2206         if (options.useXstack) {       
2207             pic14_emitcode("movx","a,@%s",r->name);
2208             //pic14_emitcode("mov","(%s+%d),a",
2209             //       regspic14[i].base,8*bank+regspic14[i].offset);
2210             pic14_emitcode("dec","%s",r->name);
2211
2212         } else 
2213           pic14_emitcode("pop",""); //"(%s+%d)",
2214         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2215     }
2216
2217     if (options.useXstack) {
2218
2219         pic14_emitcode("mov","_spx,%s",r->name);
2220         freeAsmop(NULL,aop,ic,TRUE);
2221
2222     }
2223 #endif 
2224 }
2225
2226 /*-----------------------------------------------------------------*/
2227 /* saverbank - saves an entire register bank on the stack          */
2228 /*-----------------------------------------------------------------*/
2229 static void saverbank (int bank, iCode *ic, bool pushPsw)
2230 {
2231   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2232 #if 0
2233     int i;
2234     asmop *aop ;
2235     regs *r = NULL;
2236
2237     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2238     if (options.useXstack) {
2239
2240         aop = newAsmop(0);
2241         r = getFreePtr(ic,&aop,FALSE);  
2242         pic14_emitcode("mov","%s,_spx",r->name);
2243
2244     }
2245
2246     for (i = 0 ; i < pic14_nRegs ;i++) {
2247         if (options.useXstack) {
2248             pic14_emitcode("inc","%s",r->name);
2249             //pic14_emitcode("mov","a,(%s+%d)",
2250             //         regspic14[i].base,8*bank+regspic14[i].offset);
2251             pic14_emitcode("movx","@%s,a",r->name);           
2252         } else 
2253           pic14_emitcode("push","");// "(%s+%d)",
2254                      //regspic14[i].base,8*bank+regspic14[i].offset);
2255     }
2256     
2257     if (pushPsw) {
2258         if (options.useXstack) {
2259             pic14_emitcode("mov","a,psw");
2260             pic14_emitcode("movx","@%s,a",r->name);     
2261             pic14_emitcode("inc","%s",r->name);
2262             pic14_emitcode("mov","_spx,%s",r->name);       
2263             freeAsmop (NULL,aop,ic,TRUE);
2264             
2265         } else
2266             pic14_emitcode("push","psw");
2267         
2268         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2269     }
2270     ic->bankSaved = 1;
2271 #endif
2272 }
2273
2274 /*-----------------------------------------------------------------*/
2275 /* genCall - generates a call statement                            */
2276 /*-----------------------------------------------------------------*/
2277 static void genCall (iCode *ic)
2278 {
2279   sym_link *dtype;   
2280
2281   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2282
2283   /* if caller saves & we have not saved then */
2284   if (!ic->regsSaved)
2285     saveRegisters(ic);
2286
2287   /* if we are calling a function that is not using
2288      the same register bank then we need to save the
2289      destination registers on the stack */
2290   dtype = operandType(IC_LEFT(ic));
2291   if (currFunc && dtype && 
2292       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2293       IFFUNC_ISISR(currFunc->type) &&
2294       !ic->bankSaved) 
2295
2296     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2297
2298   /* if send set is not empty the assign */
2299   if (_G.sendSet) {
2300     iCode *sic;
2301     /* For the Pic port, there is no data stack.
2302      * So parameters passed to functions are stored
2303      * in registers. (The pCode optimizer will get
2304      * rid of most of these :).
2305      */
2306     int psuedoStkPtr=-1; 
2307     int firstTimeThruLoop = 1;
2308
2309     _G.sendSet = reverseSet(_G.sendSet);
2310
2311     /* First figure how many parameters are getting passed */
2312     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2313          sic = setNextItem(_G.sendSet)) {
2314
2315       aopOp(IC_LEFT(sic),sic,FALSE);
2316       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2317       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2318     }
2319
2320     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2321          sic = setNextItem(_G.sendSet)) {
2322       int size, offset = 0;
2323
2324       aopOp(IC_LEFT(sic),sic,FALSE);
2325       size = AOP_SIZE(IC_LEFT(sic));
2326
2327
2328       while (size--) {
2329         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2330                              AopType(AOP_TYPE(IC_LEFT(sic))));
2331
2332         if(!firstTimeThruLoop) {
2333           /* If this is not the first time we've been through the loop
2334            * then we need to save the parameter in a temporary
2335            * register. The last byte of the last parameter is
2336            * passed in W. */
2337           emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr));
2338
2339         }
2340         firstTimeThruLoop=0;
2341
2342         //if (strcmp(l,fReturn[offset])) {
2343
2344         if ( ((AOP(IC_LEFT(sic))->type) == AOP_IMMD) ||
2345              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2346           emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset));
2347         else
2348           emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset));
2349
2350         //}
2351         offset++;
2352       }
2353       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2354     }
2355     _G.sendSet = NULL;
2356   }
2357   /* make the call */
2358   emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2359                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2360                                       OP_SYMBOL(IC_LEFT(ic))->name));
2361
2362   GpsuedoStkPtr=0;
2363   /* if we need assign a result value */
2364   if ((IS_ITEMP(IC_RESULT(ic)) && 
2365        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2366         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2367       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2368
2369     _G.accInUse++;
2370     aopOp(IC_RESULT(ic),ic,FALSE);
2371     _G.accInUse--;
2372
2373     assignResultValue(IC_RESULT(ic));
2374
2375     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2376                          AopType(AOP_TYPE(IC_RESULT(ic))));
2377                 
2378     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2379   }
2380
2381   /* adjust the stack for parameters if 
2382      required */
2383   if (ic->parmBytes) {
2384     int i;
2385     if (ic->parmBytes > 3) {
2386       pic14_emitcode("mov","a,%s",spname);
2387       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2388       pic14_emitcode("mov","%s,a",spname);
2389     } else 
2390       for ( i = 0 ; i <  ic->parmBytes ;i++)
2391         pic14_emitcode("dec","%s",spname);
2392
2393   }
2394
2395   /* if register bank was saved then pop them */
2396   if (ic->bankSaved)
2397     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2398
2399   /* if we hade saved some registers then unsave them */
2400   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2401     unsaveRegisters (ic);
2402
2403
2404 }
2405
2406 /*-----------------------------------------------------------------*/
2407 /* genPcall - generates a call by pointer statement                */
2408 /*-----------------------------------------------------------------*/
2409 static void genPcall (iCode *ic)
2410 {
2411     sym_link *dtype;
2412     symbol *rlbl = newiTempLabel(NULL);
2413
2414
2415     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2416     /* if caller saves & we have not saved then */
2417     if (!ic->regsSaved)
2418         saveRegisters(ic);
2419
2420     /* if we are calling a function that is not using
2421     the same register bank then we need to save the
2422     destination registers on the stack */
2423     dtype = operandType(IC_LEFT(ic));
2424     if (currFunc && dtype && 
2425         IFFUNC_ISISR(currFunc->type) &&
2426         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2427         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2428
2429
2430     /* push the return address on to the stack */
2431     pic14_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2432     pic14_emitcode("push","acc");    
2433     pic14_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2434     pic14_emitcode("push","acc");
2435     
2436     if (options.model == MODEL_FLAT24)
2437     {
2438         pic14_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2439         pic14_emitcode("push","acc");    
2440     }
2441
2442     /* now push the calling address */
2443     aopOp(IC_LEFT(ic),ic,FALSE);
2444
2445     pushSide(IC_LEFT(ic), FPTRSIZE);
2446
2447     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2448
2449     /* if send set is not empty the assign */
2450     if (_G.sendSet) {
2451         iCode *sic ;
2452
2453         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2454              sic = setNextItem(_G.sendSet)) {
2455             int size, offset = 0;
2456             aopOp(IC_LEFT(sic),sic,FALSE);
2457             size = AOP_SIZE(IC_LEFT(sic));
2458             while (size--) {
2459                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2460                                 FALSE,FALSE);
2461                 if (strcmp(l,fReturn[offset]))
2462                     pic14_emitcode("mov","%s,%s",
2463                              fReturn[offset],
2464                              l);
2465                 offset++;
2466             }
2467             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2468         }
2469         _G.sendSet = NULL;
2470     }
2471
2472     pic14_emitcode("ret","");
2473     pic14_emitcode("","%05d_DS_:",(rlbl->key+100));
2474
2475
2476     /* if we need assign a result value */
2477     if ((IS_ITEMP(IC_RESULT(ic)) &&
2478          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2479           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2480         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2481
2482         _G.accInUse++;
2483         aopOp(IC_RESULT(ic),ic,FALSE);
2484         _G.accInUse--;
2485         
2486         assignResultValue(IC_RESULT(ic));
2487
2488         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2489     }
2490
2491     /* adjust the stack for parameters if 
2492     required */
2493     if (ic->parmBytes) {
2494         int i;
2495         if (ic->parmBytes > 3) {
2496             pic14_emitcode("mov","a,%s",spname);
2497             pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2498             pic14_emitcode("mov","%s,a",spname);
2499         } else 
2500             for ( i = 0 ; i <  ic->parmBytes ;i++)
2501                 pic14_emitcode("dec","%s",spname);
2502
2503     }
2504
2505     /* if register bank was saved then unsave them */
2506     if (currFunc && dtype && 
2507         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2508         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2509
2510     /* if we hade saved some registers then
2511     unsave them */
2512     if (ic->regsSaved)
2513         unsaveRegisters (ic);
2514
2515 }
2516
2517 /*-----------------------------------------------------------------*/
2518 /* resultRemat - result  is rematerializable                       */
2519 /*-----------------------------------------------------------------*/
2520 static int resultRemat (iCode *ic)
2521 {
2522     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2523     if (SKIP_IC(ic) || ic->op == IFX)
2524         return 0;
2525
2526     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2527         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2528         if (sym->remat && !POINTER_SET(ic)) 
2529             return 1;
2530     }
2531
2532     return 0;
2533 }
2534
2535 #if defined(__BORLANDC__) || defined(_MSC_VER)
2536 #define STRCASECMP stricmp
2537 #else
2538 #define STRCASECMP strcasecmp
2539 #endif
2540
2541 #if 0
2542 /*-----------------------------------------------------------------*/
2543 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2544 /*-----------------------------------------------------------------*/
2545 static bool inExcludeList(char *s)
2546 {
2547   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2548     int i =0;
2549     
2550     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2551     if (options.excludeRegs[i] &&
2552     STRCASECMP(options.excludeRegs[i],"none") == 0)
2553         return FALSE ;
2554
2555     for ( i = 0 ; options.excludeRegs[i]; i++) {
2556         if (options.excludeRegs[i] &&
2557         STRCASECMP(s,options.excludeRegs[i]) == 0)
2558             return TRUE;
2559     }
2560     return FALSE ;
2561 }
2562 #endif
2563
2564 /*-----------------------------------------------------------------*/
2565 /* genFunction - generated code for function entry                 */
2566 /*-----------------------------------------------------------------*/
2567 static void genFunction (iCode *ic)
2568 {
2569     symbol *sym;
2570     sym_link *ftype;
2571
2572     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2573
2574     labelOffset += (max_key+4);
2575     max_key=0;
2576     GpsuedoStkPtr=0;
2577     _G.nRegsSaved = 0;
2578     /* create the function header */
2579     pic14_emitcode(";","-----------------------------------------");
2580     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2581     pic14_emitcode(";","-----------------------------------------");
2582
2583     pic14_emitcode("","%s:",sym->rname);
2584     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2585
2586     ftype = operandType(IC_LEFT(ic));
2587
2588     /* if critical function then turn interrupts off */
2589     if (IFFUNC_ISCRITICAL(ftype))
2590         pic14_emitcode("clr","ea");
2591
2592     /* here we need to generate the equates for the
2593        register bank if required */
2594 #if 0
2595     if (FUNC_REGBANK(ftype) != rbank) {
2596         int i ;
2597
2598         rbank = FUNC_REGBANK(ftype);
2599         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2600             if (strcmp(regspic14[i].base,"0") == 0)
2601                 pic14_emitcode("","%s = 0x%02x",
2602                          regspic14[i].dname,
2603                          8*rbank+regspic14[i].offset);
2604             else
2605                 pic14_emitcode ("","%s = %s + 0x%02x",
2606                           regspic14[i].dname,
2607                           regspic14[i].base,
2608                           8*rbank+regspic14[i].offset);
2609         }
2610     }
2611 #endif
2612
2613     /* if this is an interrupt service routine then
2614     save acc, b, dpl, dph  */
2615     if (IFFUNC_ISISR(sym->type)) {
2616       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2617       emitpcodeNULLop(POC_NOP);
2618       emitpcodeNULLop(POC_NOP);
2619       emitpcodeNULLop(POC_NOP);
2620       emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2621       emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2622       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2623       emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2624
2625       pBlockConvert2ISR(pb);
2626 #if 0  
2627         if (!inExcludeList("acc"))          
2628             pic14_emitcode ("push","acc");      
2629         if (!inExcludeList("b"))
2630             pic14_emitcode ("push","b");
2631         if (!inExcludeList("dpl"))
2632             pic14_emitcode ("push","dpl");
2633         if (!inExcludeList("dph"))
2634             pic14_emitcode ("push","dph");
2635         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2636         {
2637             pic14_emitcode ("push", "dpx");
2638             /* Make sure we're using standard DPTR */
2639             pic14_emitcode ("push", "dps");
2640             pic14_emitcode ("mov", "dps, #0x00");
2641             if (options.stack10bit)
2642             {   
2643                 /* This ISR could conceivably use DPTR2. Better save it. */
2644                 pic14_emitcode ("push", "dpl1");
2645                 pic14_emitcode ("push", "dph1");
2646                 pic14_emitcode ("push", "dpx1");
2647             }
2648         }
2649         /* if this isr has no bank i.e. is going to
2650            run with bank 0 , then we need to save more
2651            registers :-) */
2652         if (!FUNC_REGBANK(sym->type)) {
2653
2654             /* if this function does not call any other
2655                function then we can be economical and
2656                save only those registers that are used */
2657             if (! IFFUNC_HASFCALL(sym->type)) {
2658                 int i;
2659
2660                 /* if any registers used */
2661                 if (sym->regsUsed) {
2662                     /* save the registers used */
2663                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2664                         if (bitVectBitValue(sym->regsUsed,i) ||
2665                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2666                           pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);                         
2667                     }
2668                 }
2669                 
2670             } else {
2671                 /* this function has  a function call cannot
2672                    determines register usage so we will have the
2673                    entire bank */
2674                 saverbank(0,ic,FALSE);
2675             }       
2676         }
2677 #endif
2678     } else {
2679         /* if callee-save to be used for this function
2680            then save the registers being used in this function */
2681         if (IFFUNC_CALLEESAVES(sym->type)) {
2682             int i;
2683             
2684             /* if any registers used */
2685             if (sym->regsUsed) {
2686                 /* save the registers used */
2687                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2688                     if (bitVectBitValue(sym->regsUsed,i) ||
2689                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2690                       //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2691                         _G.nRegsSaved++;
2692                     }
2693                 }
2694             }
2695         }
2696     }
2697
2698     /* set the register bank to the desired value */
2699     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2700         pic14_emitcode("push","psw");
2701         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2702     }
2703
2704     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2705
2706         if (options.useXstack) {
2707             pic14_emitcode("mov","r0,%s",spname);
2708             pic14_emitcode("mov","a,_bp");
2709             pic14_emitcode("movx","@r0,a");
2710             pic14_emitcode("inc","%s",spname);
2711         }
2712         else
2713         {
2714             /* set up the stack */
2715             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2716         }
2717         pic14_emitcode ("mov","_bp,%s",spname);
2718     }
2719
2720     /* adjust the stack for the function */
2721     if (sym->stack) {
2722
2723         int i = sym->stack;
2724         if (i > 256 ) 
2725             werror(W_STACK_OVERFLOW,sym->name);
2726
2727         if (i > 3 && sym->recvSize < 4) {              
2728
2729             pic14_emitcode ("mov","a,sp");
2730             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2731             pic14_emitcode ("mov","sp,a");
2732            
2733         }
2734         else
2735             while(i--)
2736                 pic14_emitcode("inc","sp");
2737     }
2738
2739      if (sym->xstack) {
2740
2741         pic14_emitcode ("mov","a,_spx");
2742         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2743         pic14_emitcode ("mov","_spx,a");
2744     }    
2745
2746 }
2747
2748 /*-----------------------------------------------------------------*/
2749 /* genEndFunction - generates epilogue for functions               */
2750 /*-----------------------------------------------------------------*/
2751 static void genEndFunction (iCode *ic)
2752 {
2753     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2754
2755     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2756
2757     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2758     {
2759         pic14_emitcode ("mov","%s,_bp",spname);
2760     }
2761
2762     /* if use external stack but some variables were
2763     added to the local stack then decrement the
2764     local stack */
2765     if (options.useXstack && sym->stack) {      
2766         pic14_emitcode("mov","a,sp");
2767         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2768         pic14_emitcode("mov","sp,a");
2769     }
2770
2771
2772     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2773         if (options.useXstack) {
2774             pic14_emitcode("mov","r0,%s",spname);
2775             pic14_emitcode("movx","a,@r0");
2776             pic14_emitcode("mov","_bp,a");
2777             pic14_emitcode("dec","%s",spname);
2778         }
2779         else
2780         {
2781             pic14_emitcode ("pop","_bp");
2782         }
2783     }
2784
2785     /* restore the register bank  */    
2786     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2787         pic14_emitcode ("pop","psw");
2788
2789     if (IFFUNC_ISISR(sym->type)) {
2790
2791         /* now we need to restore the registers */
2792         /* if this isr has no bank i.e. is going to
2793            run with bank 0 , then we need to save more
2794            registers :-) */
2795         if (!FUNC_REGBANK(sym->type)) {
2796             
2797             /* if this function does not call any other
2798                function then we can be economical and
2799                save only those registers that are used */
2800             if (! IFFUNC_HASFCALL(sym->type)) {
2801                 int i;
2802                 
2803                 /* if any registers used */
2804                 if (sym->regsUsed) {
2805                     /* save the registers used */
2806                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2807                         if (bitVectBitValue(sym->regsUsed,i) ||
2808                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2809                           pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2810                     }
2811                 }
2812                 
2813             } else {
2814                 /* this function has  a function call cannot
2815                    determines register usage so we will have the
2816                    entire bank */
2817                 unsaverbank(0,ic,FALSE);
2818             }       
2819         }
2820 #if 0
2821         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2822         {
2823             if (options.stack10bit)
2824             {
2825                 pic14_emitcode ("pop", "dpx1");
2826                 pic14_emitcode ("pop", "dph1");
2827                 pic14_emitcode ("pop", "dpl1");
2828             }   
2829             pic14_emitcode ("pop", "dps");
2830             pic14_emitcode ("pop", "dpx");
2831         }
2832         if (!inExcludeList("dph"))
2833             pic14_emitcode ("pop","dph");
2834         if (!inExcludeList("dpl"))
2835             pic14_emitcode ("pop","dpl");
2836         if (!inExcludeList("b"))
2837             pic14_emitcode ("pop","b");
2838         if (!inExcludeList("acc"))
2839             pic14_emitcode ("pop","acc");
2840
2841         if (IFFUNC_ISCRITICAL(sym->type))
2842             pic14_emitcode("setb","ea");
2843 #endif
2844
2845         /* if debug then send end of function */
2846 /*      if (options.debug && currFunc) { */
2847         if (currFunc) {
2848             _G.debugLine = 1;
2849             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2850                      FileBaseName(ic->filename),currFunc->lastLine,
2851                      ic->level,ic->block); 
2852             if (IS_STATIC(currFunc->etype))         
2853                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2854             else
2855                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2856             _G.debugLine = 0;
2857         }
2858         
2859         pic14_emitcode ("reti","");
2860
2861         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2862         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2863         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2864         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2865         emitpcode(POC_MOVFW,  popCopyReg(&pc_wsave));
2866         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2867
2868         emitpcodeNULLop(POC_RETFIE);
2869
2870     }
2871     else {
2872         if (IFFUNC_ISCRITICAL(sym->type))
2873             pic14_emitcode("setb","ea");
2874         
2875         if (IFFUNC_CALLEESAVES(sym->type)) {
2876             int i;
2877             
2878             /* if any registers used */
2879             if (sym->regsUsed) {
2880                 /* save the registers used */
2881                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2882                     if (bitVectBitValue(sym->regsUsed,i) ||
2883                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2884                       pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2885                 }
2886             }
2887             
2888         }
2889
2890         /* if debug then send end of function */
2891         if (currFunc) {
2892             _G.debugLine = 1;
2893             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2894                      FileBaseName(ic->filename),currFunc->lastLine,
2895                      ic->level,ic->block); 
2896             if (IS_STATIC(currFunc->etype))         
2897                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2898             else
2899                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2900             _G.debugLine = 0;
2901         }
2902
2903         pic14_emitcode ("return","");
2904         emitpcodeNULLop(POC_RETURN);
2905
2906         /* Mark the end of a function */
2907         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2908     }
2909
2910 }
2911
2912 /*-----------------------------------------------------------------*/
2913 /* genRet - generate code for return statement                     */
2914 /*-----------------------------------------------------------------*/
2915 static void genRet (iCode *ic)
2916 {
2917   int size,offset = 0 , pushed = 0;
2918     
2919   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2920   /* if we have no return value then
2921      just generate the "ret" */
2922   if (!IC_LEFT(ic)) 
2923     goto jumpret;       
2924     
2925   /* we have something to return then
2926      move the return value into place */
2927   aopOp(IC_LEFT(ic),ic,FALSE);
2928   size = AOP_SIZE(IC_LEFT(ic));
2929     
2930   while (size--) {
2931     char *l ;
2932     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2933       /* #NOCHANGE */
2934       l = aopGet(AOP(IC_LEFT(ic)),offset++,
2935                  FALSE,TRUE);
2936       pic14_emitcode("push","%s",l);
2937       pushed++;
2938     } else {
2939       l = aopGet(AOP(IC_LEFT(ic)),offset,
2940                  FALSE,FALSE);
2941       if (strcmp(fReturn[offset],l)) {
2942         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2943             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2944           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2945         }else {
2946           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2947         }
2948         if(size) {
2949           emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
2950           pic14_emitcode("movwf","%s",fReturn[offset]);
2951         }
2952         offset++;
2953       }
2954     }
2955   }    
2956
2957   if (pushed) {
2958     while(pushed) {
2959       pushed--;
2960       if (strcmp(fReturn[pushed],"a"))
2961         pic14_emitcode("pop",fReturn[pushed]);
2962       else
2963         pic14_emitcode("pop","acc");
2964     }
2965   }
2966   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2967     
2968  jumpret:
2969   /* generate a jump to the return label
2970      if the next is not the return statement */
2971   if (!(ic->next && ic->next->op == LABEL &&
2972         IC_LABEL(ic->next) == returnLabel)) {
2973         
2974     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2975     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2976   }
2977     
2978 }
2979
2980 /*-----------------------------------------------------------------*/
2981 /* genLabel - generates a label                                    */
2982 /*-----------------------------------------------------------------*/
2983 static void genLabel (iCode *ic)
2984 {
2985     /* special case never generate */
2986     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2987     if (IC_LABEL(ic) == entryLabel)
2988         return ;
2989
2990     emitpLabel(IC_LABEL(ic)->key);
2991     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
2992 }
2993
2994 /*-----------------------------------------------------------------*/
2995 /* genGoto - generates a goto                                      */
2996 /*-----------------------------------------------------------------*/
2997 //tsd
2998 static void genGoto (iCode *ic)
2999 {
3000   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3001   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3002 }
3003
3004
3005 /*-----------------------------------------------------------------*/
3006 /* genMultbits :- multiplication of bits                           */
3007 /*-----------------------------------------------------------------*/
3008 static void genMultbits (operand *left, 
3009                          operand *right, 
3010                          operand *result)
3011 {
3012   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3013
3014   if(!pic14_sameRegs(AOP(result),AOP(right)))
3015     emitpcode(POC_BSF,  popGet(AOP(result),0));
3016
3017   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3018   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3019   emitpcode(POC_BCF,  popGet(AOP(result),0));
3020
3021 }
3022
3023
3024 /*-----------------------------------------------------------------*/
3025 /* genMultOneByte : 8 bit multiplication & division                */
3026 /*-----------------------------------------------------------------*/
3027 static void genMultOneByte (operand *left,
3028                             operand *right,
3029                             operand *result)
3030 {
3031   sym_link *opetype = operandType(result);
3032
3033   // symbol *lbl ;
3034   int size,offset;
3035
3036   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3037   DEBUGpic14_AopType(__LINE__,left,right,result);
3038   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3039
3040   /* (if two literals, the value is computed before) */
3041   /* if one literal, literal on the right */
3042   if (AOP_TYPE(left) == AOP_LIT){
3043     operand *t = right;
3044     right = left;
3045     left = t;
3046   }
3047
3048   size = AOP_SIZE(result);
3049   if(size == 1) {
3050
3051     if (AOP_TYPE(right) == AOP_LIT){
3052       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3053                      aopGet(AOP(right),0,FALSE,FALSE), 
3054                      aopGet(AOP(left),0,FALSE,FALSE), 
3055                      aopGet(AOP(result),0,FALSE,FALSE));
3056       pic14_emitcode("call","genMultLit");
3057     } else {
3058       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3059                      aopGet(AOP(right),0,FALSE,FALSE), 
3060                      aopGet(AOP(left),0,FALSE,FALSE), 
3061                      aopGet(AOP(result),0,FALSE,FALSE));
3062       pic14_emitcode("call","genMult8X8_8");
3063
3064     }
3065     genMult8X8_8 (left, right,result);
3066
3067
3068     /* signed or unsigned */
3069     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3070     //l = aopGet(AOP(left),0,FALSE,FALSE);
3071     //MOVA(l);       
3072     //pic14_emitcode("mul","ab");
3073     /* if result size = 1, mul signed = mul unsigned */
3074     //aopPut(AOP(result),"a",0);
3075
3076   } else {  // (size > 1)
3077
3078     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3079                    aopGet(AOP(right),0,FALSE,FALSE), 
3080                    aopGet(AOP(left),0,FALSE,FALSE), 
3081                    aopGet(AOP(result),0,FALSE,FALSE));
3082
3083     if (SPEC_USIGN(opetype)){
3084       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3085       genUMult8X8_16 (left, right, result, NULL);
3086
3087       if (size > 2) {
3088         /* for filling the MSBs */
3089         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3090         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3091       }
3092     }
3093     else{
3094       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3095
3096       pic14_emitcode("mov","a,b");
3097
3098       /* adjust the MSB if left or right neg */
3099
3100       /* if one literal */
3101       if (AOP_TYPE(right) == AOP_LIT){
3102         pic14_emitcode("multiply ","right is a lit");
3103         /* AND literal negative */
3104         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3105           /* adjust MSB (c==0 after mul) */
3106           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3107         }
3108       }
3109       else{
3110         genSMult8X8_16 (left, right, result, NULL);
3111       }
3112
3113       if(size > 2){
3114         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3115         /* get the sign */
3116         pic14_emitcode("rlc","a");
3117         pic14_emitcode("subb","a,acc");
3118       }
3119     }
3120
3121     size -= 2;   
3122     offset = 2;
3123     if (size > 0)
3124       while (size--)
3125         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3126     //aopPut(AOP(result),"a",offset++);
3127   }
3128 }
3129
3130 /*-----------------------------------------------------------------*/
3131 /* genMult - generates code for multiplication                     */
3132 /*-----------------------------------------------------------------*/
3133 static void genMult (iCode *ic)
3134 {
3135     operand *left = IC_LEFT(ic);
3136     operand *right = IC_RIGHT(ic);
3137     operand *result= IC_RESULT(ic);   
3138
3139     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3140     /* assign the amsops */
3141     aopOp (left,ic,FALSE);
3142     aopOp (right,ic,FALSE);
3143     aopOp (result,ic,TRUE);
3144
3145   DEBUGpic14_AopType(__LINE__,left,right,result);
3146
3147     /* special cases first */
3148     /* both are bits */
3149     if (AOP_TYPE(left) == AOP_CRY &&
3150         AOP_TYPE(right)== AOP_CRY) {
3151         genMultbits(left,right,result);
3152         goto release ;
3153     }
3154
3155     /* if both are of size == 1 */
3156     if (AOP_SIZE(left) == 1 &&
3157         AOP_SIZE(right) == 1 ) {
3158         genMultOneByte(left,right,result);
3159         goto release ;
3160     }
3161
3162     pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3163
3164     /* should have been converted to function call */
3165     //assert(0) ;
3166
3167 release :
3168     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3169     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3170     freeAsmop(result,NULL,ic,TRUE); 
3171 }
3172
3173 /*-----------------------------------------------------------------*/
3174 /* genDivbits :- division of bits                                  */
3175 /*-----------------------------------------------------------------*/
3176 static void genDivbits (operand *left, 
3177                         operand *right, 
3178                         operand *result)
3179 {
3180
3181     char *l;
3182
3183     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3184     /* the result must be bit */    
3185     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3186     l = aopGet(AOP(left),0,FALSE,FALSE);
3187
3188     MOVA(l);    
3189
3190     pic14_emitcode("div","ab");
3191     pic14_emitcode("rrc","a");
3192     aopPut(AOP(result),"c",0);
3193 }
3194
3195 /*-----------------------------------------------------------------*/
3196 /* genDivOneByte : 8 bit division                                  */
3197 /*-----------------------------------------------------------------*/
3198 static void genDivOneByte (operand *left,
3199                            operand *right,
3200                            operand *result)
3201 {
3202     sym_link *opetype = operandType(result);
3203     char *l ;
3204     symbol *lbl ;
3205     int size,offset;
3206
3207     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3208     size = AOP_SIZE(result) - 1;
3209     offset = 1;
3210     /* signed or unsigned */
3211     if (SPEC_USIGN(opetype)) {
3212         /* unsigned is easy */
3213         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3214         l = aopGet(AOP(left),0,FALSE,FALSE);
3215         MOVA(l);        
3216         pic14_emitcode("div","ab");
3217         aopPut(AOP(result),"a",0);
3218         while (size--)
3219             aopPut(AOP(result),zero,offset++);
3220         return ;
3221     }
3222
3223     /* signed is a little bit more difficult */
3224
3225     /* save the signs of the operands */
3226     l = aopGet(AOP(left),0,FALSE,FALSE);    
3227     MOVA(l);    
3228     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3229     pic14_emitcode("push","acc"); /* save it on the stack */
3230
3231     /* now sign adjust for both left & right */
3232     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3233     MOVA(l);       
3234     lbl = newiTempLabel(NULL);
3235     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3236     pic14_emitcode("cpl","a");   
3237     pic14_emitcode("inc","a");
3238     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3239     pic14_emitcode("mov","b,a");
3240
3241     /* sign adjust left side */
3242     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3243     MOVA(l);
3244
3245     lbl = newiTempLabel(NULL);
3246     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3247     pic14_emitcode("cpl","a");
3248     pic14_emitcode("inc","a");
3249     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3250
3251     /* now the division */
3252     pic14_emitcode("div","ab");
3253     /* we are interested in the lower order
3254     only */
3255     pic14_emitcode("mov","b,a");
3256     lbl = newiTempLabel(NULL);
3257     pic14_emitcode("pop","acc");   
3258     /* if there was an over flow we don't 
3259     adjust the sign of the result */
3260     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3261     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3262     CLRC;
3263     pic14_emitcode("clr","a");
3264     pic14_emitcode("subb","a,b");
3265     pic14_emitcode("mov","b,a");
3266     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3267
3268     /* now we are done */
3269     aopPut(AOP(result),"b",0);
3270     if(size > 0){
3271         pic14_emitcode("mov","c,b.7");
3272         pic14_emitcode("subb","a,acc");   
3273     }
3274     while (size--)
3275         aopPut(AOP(result),"a",offset++);
3276
3277 }
3278
3279 /*-----------------------------------------------------------------*/
3280 /* genDiv - generates code for division                            */
3281 /*-----------------------------------------------------------------*/
3282 static void genDiv (iCode *ic)
3283 {
3284     operand *left = IC_LEFT(ic);
3285     operand *right = IC_RIGHT(ic);
3286     operand *result= IC_RESULT(ic);   
3287
3288     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3289     /* assign the amsops */
3290     aopOp (left,ic,FALSE);
3291     aopOp (right,ic,FALSE);
3292     aopOp (result,ic,TRUE);
3293
3294     /* special cases first */
3295     /* both are bits */
3296     if (AOP_TYPE(left) == AOP_CRY &&
3297         AOP_TYPE(right)== AOP_CRY) {
3298         genDivbits(left,right,result);
3299         goto release ;
3300     }
3301
3302     /* if both are of size == 1 */
3303     if (AOP_SIZE(left) == 1 &&
3304         AOP_SIZE(right) == 1 ) {
3305         genDivOneByte(left,right,result);
3306         goto release ;
3307     }
3308
3309     /* should have been converted to function call */
3310     assert(0);
3311 release :
3312     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3313     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3314     freeAsmop(result,NULL,ic,TRUE); 
3315 }
3316
3317 /*-----------------------------------------------------------------*/
3318 /* genModbits :- modulus of bits                                   */
3319 /*-----------------------------------------------------------------*/
3320 static void genModbits (operand *left, 
3321                         operand *right, 
3322                         operand *result)
3323 {
3324
3325     char *l;
3326
3327     /* the result must be bit */    
3328     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3329     l = aopGet(AOP(left),0,FALSE,FALSE);
3330
3331     MOVA(l);       
3332
3333     pic14_emitcode("div","ab");
3334     pic14_emitcode("mov","a,b");
3335     pic14_emitcode("rrc","a");
3336     aopPut(AOP(result),"c",0);
3337 }
3338
3339 /*-----------------------------------------------------------------*/
3340 /* genModOneByte : 8 bit modulus                                   */
3341 /*-----------------------------------------------------------------*/
3342 static void genModOneByte (operand *left,
3343                            operand *right,
3344                            operand *result)
3345 {
3346     sym_link *opetype = operandType(result);
3347     char *l ;
3348     symbol *lbl ;
3349
3350     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3351     /* signed or unsigned */
3352     if (SPEC_USIGN(opetype)) {
3353         /* unsigned is easy */
3354         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3355         l = aopGet(AOP(left),0,FALSE,FALSE);
3356         MOVA(l);    
3357         pic14_emitcode("div","ab");
3358         aopPut(AOP(result),"b",0);
3359         return ;
3360     }
3361
3362     /* signed is a little bit more difficult */
3363
3364     /* save the signs of the operands */
3365     l = aopGet(AOP(left),0,FALSE,FALSE);    
3366     MOVA(l);
3367
3368     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3369     pic14_emitcode("push","acc"); /* save it on the stack */
3370
3371     /* now sign adjust for both left & right */
3372     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3373     MOVA(l);
3374
3375     lbl = newiTempLabel(NULL);
3376     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3377     pic14_emitcode("cpl","a");   
3378     pic14_emitcode("inc","a");
3379     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3380     pic14_emitcode("mov","b,a"); 
3381
3382     /* sign adjust left side */
3383     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3384     MOVA(l);
3385
3386     lbl = newiTempLabel(NULL);
3387     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3388     pic14_emitcode("cpl","a");   
3389     pic14_emitcode("inc","a");
3390     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3391
3392     /* now the multiplication */
3393     pic14_emitcode("div","ab");
3394     /* we are interested in the lower order
3395     only */
3396     lbl = newiTempLabel(NULL);
3397     pic14_emitcode("pop","acc");   
3398     /* if there was an over flow we don't 
3399     adjust the sign of the result */
3400     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3401     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3402     CLRC ;
3403     pic14_emitcode("clr","a");
3404     pic14_emitcode("subb","a,b");
3405     pic14_emitcode("mov","b,a");
3406     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3407
3408     /* now we are done */
3409     aopPut(AOP(result),"b",0);
3410
3411 }
3412
3413 /*-----------------------------------------------------------------*/
3414 /* genMod - generates code for division                            */
3415 /*-----------------------------------------------------------------*/
3416 static void genMod (iCode *ic)
3417 {
3418     operand *left = IC_LEFT(ic);
3419     operand *right = IC_RIGHT(ic);
3420     operand *result= IC_RESULT(ic);  
3421
3422     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3423     /* assign the amsops */
3424     aopOp (left,ic,FALSE);
3425     aopOp (right,ic,FALSE);
3426     aopOp (result,ic,TRUE);
3427
3428     /* special cases first */
3429     /* both are bits */
3430     if (AOP_TYPE(left) == AOP_CRY &&
3431         AOP_TYPE(right)== AOP_CRY) {
3432         genModbits(left,right,result);
3433         goto release ;
3434     }
3435
3436     /* if both are of size == 1 */
3437     if (AOP_SIZE(left) == 1 &&
3438         AOP_SIZE(right) == 1 ) {
3439         genModOneByte(left,right,result);
3440         goto release ;
3441     }
3442
3443     /* should have been converted to function call */
3444     assert(0);
3445
3446 release :
3447     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3448     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3449     freeAsmop(result,NULL,ic,TRUE); 
3450 }
3451
3452 /*-----------------------------------------------------------------*/
3453 /* genIfxJump :- will create a jump depending on the ifx           */
3454 /*-----------------------------------------------------------------*/
3455 /*
3456   note: May need to add parameter to indicate when a variable is in bit space.
3457 */
3458 static void genIfxJump (iCode *ic, char *jval)
3459 {
3460
3461     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3462     /* if true label then we jump if condition
3463     supplied is true */
3464     if ( IC_TRUE(ic) ) {
3465
3466         if(strcmp(jval,"a") == 0)
3467           emitSKPZ;
3468         else if (strcmp(jval,"c") == 0)
3469           emitSKPC;
3470         else {
3471           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3472           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3473         }
3474
3475         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3476         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3477
3478     }
3479     else {
3480         /* false label is present */
3481         if(strcmp(jval,"a") == 0)
3482           emitSKPNZ;
3483         else if (strcmp(jval,"c") == 0)
3484           emitSKPNC;
3485         else {
3486           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3487           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3488         }
3489
3490         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3491         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3492
3493     }
3494
3495
3496     /* mark the icode as generated */
3497     ic->generated = 1;
3498 }
3499
3500 /*-----------------------------------------------------------------*/
3501 /* genSkip                                                         */
3502 /*-----------------------------------------------------------------*/
3503 static void genSkip(iCode *ifx,int status_bit)
3504 {
3505   if(!ifx)
3506     return;
3507
3508   if ( IC_TRUE(ifx) ) {
3509     switch(status_bit) {
3510     case 'z':
3511       emitSKPNZ;
3512       break;
3513
3514     case 'c':
3515       emitSKPNC;
3516       break;
3517
3518     case 'd':
3519       emitSKPDC;
3520       break;
3521
3522     }
3523
3524     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3525     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3526
3527   } else {
3528
3529     switch(status_bit) {
3530
3531     case 'z':
3532       emitSKPZ;
3533       break;
3534
3535     case 'c':
3536       emitSKPC;
3537       break;
3538
3539     case 'd':
3540       emitSKPDC;
3541       break;
3542     }
3543     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3544     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3545
3546   }
3547
3548 }
3549
3550 /*-----------------------------------------------------------------*/
3551 /* genSkipc                                                        */
3552 /*-----------------------------------------------------------------*/
3553 static void genSkipc(resolvedIfx *rifx)
3554 {
3555   if(!rifx)
3556     return;
3557
3558   if(rifx->condition)
3559     emitSKPC;
3560   else
3561     emitSKPNC;
3562
3563   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3564   rifx->generated = 1;
3565 }
3566
3567 /*-----------------------------------------------------------------*/
3568 /* genSkipz2                                                       */
3569 /*-----------------------------------------------------------------*/
3570 static void genSkipz2(resolvedIfx *rifx)
3571 {
3572   if(!rifx)
3573     return;
3574
3575   if(rifx->condition)
3576     emitSKPZ;
3577   else
3578     emitSKPNZ;
3579
3580   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3581   rifx->generated = 1;
3582 }
3583
3584 /*-----------------------------------------------------------------*/
3585 /* genSkipz                                                        */
3586 /*-----------------------------------------------------------------*/
3587 static void genSkipz(iCode *ifx, int condition)
3588 {
3589   if(!ifx)
3590     return;
3591
3592   if(condition)
3593     emitSKPNZ;
3594   else
3595     emitSKPZ;
3596
3597   if ( IC_TRUE(ifx) )
3598     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3599   else
3600     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3601
3602   if ( IC_TRUE(ifx) )
3603     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3604   else
3605     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3606
3607 }
3608 /*-----------------------------------------------------------------*/
3609 /* genSkipCond                                                     */
3610 /*-----------------------------------------------------------------*/
3611 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3612 {
3613   if(!rifx)
3614     return;
3615
3616   if(rifx->condition)
3617     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3618   else
3619     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3620
3621
3622   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3623   rifx->generated = 1;
3624 }
3625
3626 #if 0
3627 /*-----------------------------------------------------------------*/
3628 /* genChkZeroes :- greater or less than comparison                 */
3629 /*     For each byte in a literal that is zero, inclusive or the   */
3630 /*     the corresponding byte in the operand with W                */
3631 /*     returns true if any of the bytes are zero                   */
3632 /*-----------------------------------------------------------------*/
3633 static int genChkZeroes(operand *op, int lit,  int size)
3634 {
3635
3636   int i;
3637   int flag =1;
3638
3639   while(size--) {
3640     i = (lit >> (size*8)) & 0xff;
3641
3642     if(i==0) {
3643       if(flag) 
3644         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3645       else
3646         emitpcode(POC_IORFW, popGet(AOP(op),size));
3647       flag = 0;
3648     }
3649   }
3650
3651   return (flag==0);
3652 }
3653 #endif
3654
3655 /*-----------------------------------------------------------------*/
3656 /* genCmp :- greater or less than comparison                       */
3657 /*-----------------------------------------------------------------*/
3658 static void genCmp (operand *left,operand *right,
3659                     operand *result, iCode *ifx, int sign)
3660 {
3661   int size, offset = 0 ;
3662   unsigned long lit = 0L,i = 0;
3663   resolvedIfx rFalseIfx;
3664   //  resolvedIfx rTrueIfx;
3665   symbol *truelbl;
3666   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3667   if(ifx) {
3668   DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3669   DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3670   }
3671
3672
3673   resolveIfx(&rFalseIfx,ifx);
3674   truelbl  = newiTempLabel(NULL);
3675
3676   //if(IC_TRUE(ifx) == NULL)
3677   /* if left & right are bit variables */
3678   if (AOP_TYPE(left) == AOP_CRY &&
3679       AOP_TYPE(right) == AOP_CRY ) {
3680     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3681     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3682   } else {
3683     /* subtract right from left if at the
3684        end the carry flag is set then we know that
3685        left is greater than right */
3686     size = max(AOP_SIZE(left),AOP_SIZE(right));
3687
3688     /* if unsigned char cmp with lit, do cjne left,#right,zz */
3689     if((size == 1) && !sign &&
3690        (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3691       symbol *lbl  = newiTempLabel(NULL);
3692       pic14_emitcode("cjne","%s,%s,%05d_DS_",
3693                aopGet(AOP(left),offset,FALSE,FALSE),
3694                aopGet(AOP(right),offset,FALSE,FALSE),
3695                lbl->key+100);
3696       pic14_emitcode("","%05d_DS_:",lbl->key+100);
3697     } else {
3698
3699       symbol *lbl  = newiTempLabel(NULL);
3700
3701       if(AOP_TYPE(right) == AOP_LIT) {
3702
3703         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3704
3705         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3706
3707         /* special cases */
3708
3709         if(lit == 0) {
3710
3711           if(sign != 0) 
3712             genSkipCond(&rFalseIfx,left,size-1,7);
3713           else 
3714             /* no need to compare to 0...*/
3715             /* NOTE: this is a de-generate compare that most certainly 
3716              *       creates some dead code. */
3717             emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3718
3719           if(ifx) ifx->generated = 1;
3720           return;
3721
3722         }
3723         size--;
3724
3725         if(size == 0) {
3726           //i = (lit >> (size*8)) & 0xff;
3727           DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3728         
3729           emitpcode(POC_MOVFW, popGet(AOP(left),size));
3730
3731           i = ((0-lit) & 0xff);
3732           if(sign) {
3733             if( i == 0x81) { 
3734               /* lit is 0x7f, all signed chars are less than
3735                * this except for 0x7f itself */
3736               emitpcode(POC_XORLW, popGetLit(0x7f));
3737               genSkipz2(&rFalseIfx);
3738             } else {
3739               emitpcode(POC_ADDLW, popGetLit(0x80));
3740               emitpcode(POC_ADDLW, popGetLit(i^0x80));
3741               genSkipc(&rFalseIfx);
3742             }
3743
3744           } else {
3745             emitpcode(POC_ADDLW, popGetLit(i));
3746             genSkipc(&rFalseIfx);
3747
3748           }
3749
3750           if(ifx) ifx->generated = 1;
3751           return;
3752         }
3753
3754         /* chars are out of the way. now do ints and longs */
3755
3756
3757         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3758         
3759         /* special cases */
3760
3761         if(sign) {
3762
3763           if(lit == 0) {
3764             genSkipCond(&rFalseIfx,left,size,7);
3765             if(ifx) ifx->generated = 1;
3766             return;
3767           }
3768
3769           if(lit <0x100) {
3770             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3771
3772             //rFalseIfx.condition ^= 1;
3773             //genSkipCond(&rFalseIfx,left,size,7);
3774             //rFalseIfx.condition ^= 1;
3775
3776             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3777             if(rFalseIfx.condition)
3778               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3779             else
3780               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3781
3782             emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3783             emitpcode(POC_ADDFW, popGet(AOP(left),0));
3784             emitpcode(POC_MOVFW, popGet(AOP(left),1));
3785
3786             while(size > 1)
3787               emitpcode(POC_IORFW, popGet(AOP(left),size--));
3788
3789             if(rFalseIfx.condition) {
3790               emitSKPZ;
3791               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3792
3793             } else {
3794               emitSKPNZ;
3795             }
3796
3797             genSkipc(&rFalseIfx);
3798             emitpLabel(truelbl->key);
3799             if(ifx) ifx->generated = 1;
3800             return;
3801
3802           }
3803
3804           if(size == 1) {
3805
3806             if( (lit & 0xff) == 0) {
3807               /* lower byte is zero */
3808               DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3809               i = ((lit >> 8) & 0xff) ^0x80;
3810               emitpcode(POC_MOVFW, popGet(AOP(left),size));
3811               emitpcode(POC_ADDLW, popGetLit( 0x80));
3812               emitpcode(POC_ADDLW, popGetLit(0x100-i));
3813               genSkipc(&rFalseIfx);
3814
3815
3816               if(ifx) ifx->generated = 1;
3817               return;
3818
3819             }
3820           } else {
3821             /* Special cases for signed longs */
3822             if( (lit & 0xffffff) == 0) {
3823               /* lower byte is zero */
3824               DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3825               i = ((lit >> 8*3) & 0xff) ^0x80;
3826               emitpcode(POC_MOVFW, popGet(AOP(left),size));
3827               emitpcode(POC_ADDLW, popGetLit( 0x80));
3828               emitpcode(POC_ADDLW, popGetLit(0x100-i));
3829               genSkipc(&rFalseIfx);
3830
3831
3832               if(ifx) ifx->generated = 1;
3833               return;
3834
3835             }
3836
3837           }
3838
3839
3840           if(lit & (0x80 << (size*8))) {
3841             /* lit is negative */
3842             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3843
3844             //genSkipCond(&rFalseIfx,left,size,7);
3845
3846             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3847
3848             if(rFalseIfx.condition)
3849               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3850             else
3851               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3852
3853
3854           } else {
3855             /* lit is positive */
3856             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3857             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3858             if(rFalseIfx.condition)
3859               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3860             else
3861               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3862
3863             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3864             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3865             //rFalseIfx.condition ^= 1;
3866             //genSkipCond(&rFalseIfx,left,size,7);
3867             //rFalseIfx.condition ^= 1;
3868           }
3869
3870           /*
3871             This works, but is only good for ints.
3872             It also requires a "known zero" register.
3873             emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3874             emitpcode(POC_ADDFW, popGet(AOP(left),0));
3875             emitpcode(POC_RLFW,  popCopyReg(&pc_kzero));
3876             emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
3877             emitpcode(POC_ADDFW, popGet(AOP(left),1));
3878             genSkipc(&rFalseIfx);
3879
3880             emitpLabel(truelbl->key);
3881             if(ifx) ifx->generated = 1;
3882             return;
3883           **/
3884           
3885           /* There are no more special cases, so perform a general compare */
3886   
3887           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3888           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3889
3890           while(size--) {
3891
3892             emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3893             emitSKPNZ;
3894             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3895           }
3896           //rFalseIfx.condition ^= 1;
3897           genSkipc(&rFalseIfx);
3898
3899           emitpLabel(truelbl->key);
3900
3901           if(ifx) ifx->generated = 1;
3902           return;
3903
3904
3905         }
3906
3907
3908         /* sign is out of the way. So now do an unsigned compare */
3909         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3910
3911
3912         //genChkZeroes(left)
3913
3914         /* General case - compare to an unsigned literal on the right.*/
3915
3916         i = (lit >> (size*8)) & 0xff;
3917         emitpcode(POC_MOVLW, popGetLit(i));
3918         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3919         while(size--) {
3920           i = (lit >> (size*8)) & 0xff;
3921
3922           if(i) {
3923             emitpcode(POC_MOVLW, popGetLit(i));
3924             emitSKPNZ;
3925             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3926           } else {
3927             /* this byte of the lit is zero, 
3928              *if it's not the last then OR in the variable */
3929             if(size)
3930               emitpcode(POC_IORFW, popGet(AOP(left),size));
3931           }
3932         }
3933
3934
3935         emitpLabel(lbl->key);
3936         //if(emitFinalCheck)
3937           genSkipc(&rFalseIfx);
3938         if(sign)
3939           emitpLabel(truelbl->key);
3940
3941         if(ifx) ifx->generated = 1;
3942         return;
3943
3944
3945       }
3946
3947       if(AOP_TYPE(left) == AOP_LIT) {
3948         //symbol *lbl = newiTempLabel(NULL);
3949
3950         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3951
3952
3953         DEBUGpic14_emitcode(";left lit","lit = %d,sign=%d",lit,sign);
3954
3955         /* Special cases */
3956         if((lit == 0) && (sign == 0)){
3957
3958           size--;
3959           emitpcode(POC_MOVFW, popGet(AOP(right),size));
3960           while(size) 
3961             emitpcode(POC_IORFW, popGet(AOP(right),--size));
3962
3963           //rFalseIfx.condition ^= 1;
3964           genSkipz2(&rFalseIfx);
3965           if(ifx) ifx->generated = 1;
3966           return;
3967         }
3968
3969         if(size==1) {
3970           /* Special cases */
3971           lit &= 0xff;
3972           if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3973             /* degenerate compare can never be true */
3974             if(rFalseIfx.condition == 0)
3975               emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3976
3977             if(ifx) ifx->generated = 1;
3978             return;
3979           }
3980
3981           if(sign) {
3982             if((lit+1)&0xff) {
3983               emitpcode(POC_MOVFW, popGet(AOP(right),0));
3984               emitpcode(POC_ADDLW, popGetLit(0x80));
3985               emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
3986               rFalseIfx.condition ^= 1;
3987               genSkipc(&rFalseIfx);
3988             } else {
3989               rFalseIfx.condition ^= 1;
3990               genSkipCond(&rFalseIfx,right,0,7);
3991             }
3992             
3993           } else {
3994             if(lit & 0xff) {
3995               emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
3996               emitpcode(POC_SUBFW, popGet(AOP(right),0));
3997               DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3998               rFalseIfx.condition ^= 1;
3999               genSkipc(&rFalseIfx);
4000             } else { 
4001               emitpcode(POC_MOVFW, popGet(AOP(right),0));
4002               genSkipz2(&rFalseIfx);
4003             }
4004           }
4005
4006           if(ifx) ifx->generated = 1;
4007           return;
4008
4009         } else {
4010
4011           /* Size is greater than 1 */
4012
4013
4014
4015           if(sign) {
4016             int lp1 = lit+1;
4017
4018             size--;
4019
4020             if(lp1 == 0) {
4021               /* this means lit = 0xffffffff, or -1 */
4022
4023
4024               DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4025               rFalseIfx.condition ^= 1;
4026               genSkipCond(&rFalseIfx,right,size,7);
4027               if(ifx) ifx->generated = 1;
4028               return;
4029             }
4030
4031             if(lit == 0) {
4032               int s = size;
4033
4034               if(rFalseIfx.condition) {
4035                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4036                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4037               }
4038
4039               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4040               while(size--)
4041                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4042
4043
4044               emitSKPZ;
4045               if(rFalseIfx.condition) {
4046                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4047                 emitpLabel(truelbl->key);
4048               }else {
4049                 rFalseIfx.condition ^= 1;
4050                 genSkipCond(&rFalseIfx,right,s,7);
4051               }
4052
4053               if(ifx) ifx->generated = 1;
4054               return;
4055             }
4056
4057
4058             if(lit & (0x80 << (size*8))) {
4059               /* Lit is less than zero */
4060               DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4061               //rFalseIfx.condition ^= 1;
4062               //genSkipCond(&rFalseIfx,left,size,7);
4063               //rFalseIfx.condition ^= 1;
4064               emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4065               //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4066
4067               if(rFalseIfx.condition)
4068                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4069               else
4070                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4071
4072
4073             } else {
4074               /* Lit is greater than or equal to zero */
4075               DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4076               //rFalseIfx.condition ^= 1;
4077               //genSkipCond(&rFalseIfx,right,size,7);
4078               //rFalseIfx.condition ^= 1;
4079
4080               //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4081               //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4082
4083               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4084               if(rFalseIfx.condition)
4085                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4086               else
4087                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4088
4089             }
4090             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4091             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4092
4093             while(size--) {
4094
4095               emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4096               emitSKPNZ;
4097               emitpcode(POC_SUBFW, popGet(AOP(right),size));
4098             }
4099             rFalseIfx.condition ^= 1;
4100             //rFalseIfx.condition = 1;
4101             genSkipc(&rFalseIfx);
4102
4103             emitpLabel(truelbl->key);
4104
4105             if(ifx) ifx->generated = 1;
4106             return;
4107
4108           } else {
4109             /* Unsigned compare for sizes greater than 1 */
4110
4111             while(size--) {
4112               i = (lit >> (size*8)) & 0xff;
4113
4114
4115               if(size) {
4116                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4117                 emitpcode(POC_MOVLW, popGetLit(i&0xff));
4118                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4119                 emitSKPZ;
4120                 emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4121               } else {
4122                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4123                 emitpcode(POC_MOVLW, popGetLit((i+1)&0xff));
4124                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4125
4126               }
4127             }
4128
4129             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4130
4131             emitpLabel(lbl->key);
4132
4133             rFalseIfx.condition ^= 1;
4134             genSkipc(&rFalseIfx);
4135
4136           }
4137         if(sign)
4138           emitpLabel(truelbl->key);
4139         if(ifx) ifx->generated = 1;
4140         return;
4141         }
4142       }
4143       /* Compare two variables */
4144
4145       DEBUGpic14_emitcode(";sign","%d",sign);
4146
4147       size--;
4148       if(sign) {
4149         /* Sigh. thus sucks... */
4150         if(size) {
4151           emitpcode(POC_MOVFW, popGet(AOP(left),size));
4152           emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4153           emitpcode(POC_MOVLW, popGetLit(0x80));
4154           emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4155           emitpcode(POC_XORFW, popGet(AOP(right),size));
4156           emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4157         } else {
4158           /* Signed char comparison */
4159           /* Special thanks to Nikolai Golovchenko for this snippet */
4160           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4161           emitpcode(POC_SUBFW, popGet(AOP(left),0));
4162           emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4163           emitpcode(POC_XORFW, popGet(AOP(left),0));
4164           emitpcode(POC_XORFW, popGet(AOP(right),0));
4165           emitpcode(POC_ADDLW, popGetLit(0x80));
4166
4167           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4168           genSkipc(&rFalseIfx);
4169           
4170           if(ifx) ifx->generated = 1;
4171           return;
4172         }
4173
4174       } else {
4175
4176         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4177         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4178       }
4179
4180
4181       /* The rest of the bytes of a multi-byte compare */
4182       while (size) {
4183
4184         emitSKPZ;
4185         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4186         size--;
4187
4188         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4189         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4190
4191
4192       }
4193
4194       emitpLabel(lbl->key);
4195
4196       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4197       genSkipc(&rFalseIfx);
4198       if(ifx) ifx->generated = 1;
4199       return;
4200
4201     }
4202   }
4203
4204   //release:
4205   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4206     pic14_outBitC(result);
4207   } else {
4208     /* if the result is used in the next
4209        ifx conditional branch then generate
4210        code a little differently */
4211     if (ifx )
4212       genIfxJump (ifx,"c");
4213     else
4214       pic14_outBitC(result);
4215     /* leave the result in acc */
4216   }
4217
4218 }
4219
4220 /*-----------------------------------------------------------------*/
4221 /* genCmpGt :- greater than comparison                             */
4222 /*-----------------------------------------------------------------*/
4223 static void genCmpGt (iCode *ic, iCode *ifx)
4224 {
4225     operand *left, *right, *result;
4226     sym_link *letype , *retype;
4227     int sign ;
4228
4229     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4230     left = IC_LEFT(ic);
4231     right= IC_RIGHT(ic);
4232     result = IC_RESULT(ic);
4233
4234     letype = getSpec(operandType(left));
4235     retype =getSpec(operandType(right));
4236     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4237     /* assign the amsops */
4238     aopOp (left,ic,FALSE);
4239     aopOp (right,ic,FALSE);
4240     aopOp (result,ic,TRUE);
4241
4242     genCmp(right, left, result, ifx, sign);
4243
4244     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4245     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4246     freeAsmop(result,NULL,ic,TRUE); 
4247 }
4248
4249 /*-----------------------------------------------------------------*/
4250 /* genCmpLt - less than comparisons                                */
4251 /*-----------------------------------------------------------------*/
4252 static void genCmpLt (iCode *ic, iCode *ifx)
4253 {
4254     operand *left, *right, *result;
4255     sym_link *letype , *retype;
4256     int sign ;
4257
4258     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4259     left = IC_LEFT(ic);
4260     right= IC_RIGHT(ic);
4261     result = IC_RESULT(ic);
4262
4263     letype = getSpec(operandType(left));
4264     retype =getSpec(operandType(right));
4265     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4266
4267     /* assign the amsops */
4268     aopOp (left,ic,FALSE);
4269     aopOp (right,ic,FALSE);
4270     aopOp (result,ic,TRUE);
4271
4272     genCmp(left, right, result, ifx, sign);
4273
4274     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4275     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4276     freeAsmop(result,NULL,ic,TRUE); 
4277 }
4278
4279 /*-----------------------------------------------------------------*/
4280 /* genc16bit2lit - compare a 16 bit value to a literal             */
4281 /*-----------------------------------------------------------------*/
4282 static void genc16bit2lit(operand *op, int lit, int offset)
4283 {
4284   int i;
4285
4286   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4287   if( (lit&0xff) == 0) 
4288     i=1;
4289   else
4290     i=0;
4291
4292   switch( BYTEofLONG(lit,i)) { 
4293   case 0:
4294     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4295     break;
4296   case 1:
4297     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4298     break;
4299   case 0xff:
4300     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4301     break;
4302   default:
4303     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4304     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4305   }
4306
4307   i ^= 1;
4308
4309   switch( BYTEofLONG(lit,i)) { 
4310   case 0:
4311     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4312     break;
4313   case 1:
4314     emitSKPNZ;
4315     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4316     break;
4317   case 0xff:
4318     emitSKPNZ;
4319     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4320     break;
4321   default:
4322     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4323     emitSKPNZ;
4324     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4325
4326   }
4327
4328 }
4329
4330 /*-----------------------------------------------------------------*/
4331 /* gencjneshort - compare and jump if not equal                    */
4332 /*-----------------------------------------------------------------*/
4333 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4334 {
4335   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4336   int offset = 0;
4337   resolvedIfx rIfx;
4338   symbol *lbl;
4339
4340   unsigned long lit = 0L;
4341   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4342   DEBUGpic14_AopType(__LINE__,left,right,NULL);
4343
4344   resolveIfx(&rIfx,ifx);
4345   lbl =  newiTempLabel(NULL);
4346
4347
4348   /* if the left side is a literal or 
4349      if the right is in a pointer register and left 
4350      is not */
4351   if ((AOP_TYPE(left) == AOP_LIT) || 
4352       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4353     operand *t = right;
4354     right = left;
4355     left = t;
4356   }
4357   if(AOP_TYPE(right) == AOP_LIT)
4358     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4359
4360   /* if the right side is a literal then anything goes */
4361   if (AOP_TYPE(right) == AOP_LIT &&
4362       AOP_TYPE(left) != AOP_DIR ) {
4363     switch(size) {
4364     case 2:
4365       genc16bit2lit(left, lit, 0);
4366       emitSKPNZ;
4367       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4368       break;
4369     default:
4370       while (size--) {
4371         if(lit & 0xff) {
4372           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4373           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4374         } else {
4375           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4376         }
4377
4378         emitSKPNZ;
4379         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4380         offset++;
4381         lit >>= 8;
4382       }
4383       break;
4384     }
4385   }
4386
4387   /* if the right side is in a register or in direct space or
4388      if the left is a pointer register & right is not */    
4389   else if (AOP_TYPE(right) == AOP_REG ||
4390            AOP_TYPE(right) == AOP_DIR || 
4391            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4392            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4393     switch(size) {
4394     case 2:
4395       genc16bit2lit(left, lit, 0);
4396       emitSKPNZ;
4397       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4398       break;
4399     default:
4400       while (size--) {
4401         int emit_skip=1;
4402         if((AOP_TYPE(left) == AOP_DIR) && 
4403            ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4404
4405           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4406           emitpcode(POC_XORFW,popGet(AOP(right),offset));
4407
4408         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4409             
4410           switch (lit & 0xff) {
4411           case 0:
4412             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4413             break;
4414           case 1:
4415             emitpcode(POC_DECFSZ,popGet(AOP(left),offset));
4416             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4417             emit_skip=0;
4418             break;
4419           case 0xff:
4420             emitpcode(POC_INCFSZ,popGet(AOP(left),offset));
4421             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4422             emit_skip=0;
4423             break;
4424           default:
4425             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4426             emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4427           }
4428           lit >>= 8;
4429
4430         } else {
4431           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4432         }
4433         if(emit_skip) {
4434           if(AOP_TYPE(result) == AOP_CRY) {
4435             pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4436             if(rIfx.condition)
4437               emitSKPNZ;
4438             else
4439               emitSKPZ;
4440             emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4441           } else {
4442             /* fix me. probably need to check result size too */
4443             emitpcode(POC_CLRF,popGet(AOP(result),0));
4444             if(rIfx.condition)
4445               emitSKPNZ;
4446             else
4447               emitSKPZ;
4448             emitpcode(POC_INCF,popGet(AOP(result),0));
4449           }
4450           if(ifx)
4451             ifx->generated=1;
4452         }
4453         emit_skip++;
4454         offset++;
4455       }
4456       break;
4457     }
4458   } else if(AOP_TYPE(right) == AOP_REG &&
4459             AOP_TYPE(left) != AOP_DIR){
4460
4461     while(size--) {
4462       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4463       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4464       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4465       if(rIfx.condition)
4466         emitSKPNZ;
4467       else
4468         emitSKPZ;
4469       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4470       offset++;
4471     }
4472       
4473   }else{
4474     /* right is a pointer reg need both a & b */
4475     while(size--) {
4476       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4477       if(strcmp(l,"b"))
4478         pic14_emitcode("mov","b,%s",l);
4479       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4480       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4481       offset++;
4482     }
4483   }
4484   emitpLabel(lbl->key);
4485
4486   if(ifx)
4487     ifx->generated = 1;
4488 }
4489
4490 #if 0
4491 /*-----------------------------------------------------------------*/
4492 /* gencjne - compare and jump if not equal                         */
4493 /*-----------------------------------------------------------------*/
4494 static void gencjne(operand *left, operand *right, iCode *ifx)
4495 {
4496     symbol *tlbl  = newiTempLabel(NULL);
4497
4498     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4499     gencjneshort(left, right, lbl);
4500
4501     pic14_emitcode("mov","a,%s",one);
4502     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4503     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4504     pic14_emitcode("clr","a");
4505     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4506
4507     emitpLabel(lbl->key);
4508     emitpLabel(tlbl->key);
4509
4510 }
4511 #endif
4512
4513 /*-----------------------------------------------------------------*/
4514 /* genCmpEq - generates code for equal to                          */
4515 /*-----------------------------------------------------------------*/
4516 static void genCmpEq (iCode *ic, iCode *ifx)
4517 {
4518     operand *left, *right, *result;
4519     unsigned long lit = 0L;
4520     int size,offset=0;
4521
4522     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4523
4524     if(ifx)
4525       DEBUGpic14_emitcode ("; ifx is non-null","");
4526     else
4527       DEBUGpic14_emitcode ("; ifx is null","");
4528
4529     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4530     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4531     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4532
4533     size = max(AOP_SIZE(left),AOP_SIZE(right));
4534
4535     DEBUGpic14_AopType(__LINE__,left,right,result);
4536
4537     /* if literal, literal on the right or 
4538     if the right is in a pointer register and left 
4539     is not */
4540     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4541         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4542       operand *tmp = right ;
4543       right = left;
4544       left = tmp;
4545     }
4546
4547
4548     if(ifx && !AOP_SIZE(result)){
4549         symbol *tlbl;
4550         /* if they are both bit variables */
4551         if (AOP_TYPE(left) == AOP_CRY &&
4552             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4553             if(AOP_TYPE(right) == AOP_LIT){
4554                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4555                 if(lit == 0L){
4556                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4557                     pic14_emitcode("cpl","c");
4558                 } else if(lit == 1L) {
4559                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4560                 } else {
4561                     pic14_emitcode("clr","c");
4562                 }
4563                 /* AOP_TYPE(right) == AOP_CRY */
4564             } else {
4565                 symbol *lbl = newiTempLabel(NULL);
4566                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4567                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4568                 pic14_emitcode("cpl","c");
4569                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4570             }
4571             /* if true label then we jump if condition
4572             supplied is true */
4573             tlbl = newiTempLabel(NULL);
4574             if ( IC_TRUE(ifx) ) {
4575                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4576                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4577             } else {
4578                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4579                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4580             }
4581             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4582
4583             {
4584               /* left and right are both bit variables, result is carry */
4585               resolvedIfx rIfx;
4586               
4587               resolveIfx(&rIfx,ifx);
4588
4589               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4590               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4591               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4592               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4593               genSkipz2(&rIfx);
4594             }
4595         } else {
4596
4597           /* They're not both bit variables. Is the right a literal? */
4598           if(AOP_TYPE(right) == AOP_LIT) {
4599             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4600             
4601             switch(size) {
4602
4603             case 1:
4604               switch(lit & 0xff) {
4605               case 1:
4606                 if ( IC_TRUE(ifx) ) {
4607                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4608                   emitSKPNZ;
4609                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4610                 } else {
4611                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4612                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4613                 }
4614                 break;
4615               case 0xff:
4616                 if ( IC_TRUE(ifx) ) {
4617                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4618                   emitSKPNZ;
4619                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4620                 } else {
4621                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4622                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4623                 }
4624                 break;
4625               default:
4626                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4627                 if(lit)
4628                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4629                 genSkip(ifx,'z');
4630               }
4631
4632
4633               /* end of size == 1 */
4634               break;
4635               
4636             case 2:
4637               genc16bit2lit(left,lit,offset);
4638               genSkip(ifx,'z');
4639               break;
4640               /* end of size == 2 */
4641
4642             default:
4643               /* size is 4 */
4644               if(lit==0) {
4645                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4646                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4647                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4648                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4649
4650               } else {
4651
4652                 /* search for patterns that can be optimized */
4653
4654                 genc16bit2lit(left,lit,0);
4655                 lit >>= 16;
4656                 if(lit) {
4657                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4658                   //genSkip(ifx,'z');
4659                   genc16bit2lit(left,lit,2);
4660                 } else {
4661                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4662                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4663
4664                 }
4665                 
4666               }
4667
4668               genSkip(ifx,'z');
4669             }
4670           
4671             ifx->generated = 1;
4672             goto release ;
4673             
4674
4675           } else if(AOP_TYPE(right) == AOP_CRY ) {
4676             /* we know the left is not a bit, but that the right is */
4677             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4678             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4679                       popGet(AOP(right),offset));
4680             emitpcode(POC_XORLW,popGetLit(1));
4681
4682             /* if the two are equal, then W will be 0 and the Z bit is set
4683              * we could test Z now, or go ahead and check the high order bytes if
4684              * the variable we're comparing is larger than a byte. */
4685
4686             while(--size)
4687               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4688
4689             if ( IC_TRUE(ifx) ) {
4690               emitSKPNZ;
4691               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4692               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4693             } else {
4694               emitSKPZ;
4695               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4696               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4697             }
4698
4699           } else {
4700             /* They're both variables that are larger than bits */
4701             int s = size;
4702
4703             tlbl = newiTempLabel(NULL);
4704
4705             while(size--) {
4706               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4707               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4708
4709               if ( IC_TRUE(ifx) ) {
4710                 if(size) {
4711                   emitSKPZ;
4712                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4713                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4714                 } else {
4715                   emitSKPNZ;
4716                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4717                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4718                 }
4719               } else {
4720                 emitSKPZ;
4721                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4722                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4723               }
4724               offset++;
4725             }
4726             if(s>1 && IC_TRUE(ifx)) {
4727               emitpLabel(tlbl->key);
4728               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4729             }
4730           }
4731         }
4732         /* mark the icode as generated */
4733         ifx->generated = 1;
4734         goto release ;
4735     }
4736
4737     /* if they are both bit variables */
4738     if (AOP_TYPE(left) == AOP_CRY &&
4739         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4740         if(AOP_TYPE(right) == AOP_LIT){
4741             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4742             if(lit == 0L){
4743                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4744                 pic14_emitcode("cpl","c");
4745             } else if(lit == 1L) {
4746                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4747             } else {
4748                 pic14_emitcode("clr","c");
4749             }
4750             /* AOP_TYPE(right) == AOP_CRY */
4751         } else {
4752             symbol *lbl = newiTempLabel(NULL);
4753             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4754             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4755             pic14_emitcode("cpl","c");
4756             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4757         }
4758         /* c = 1 if egal */
4759         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4760             pic14_outBitC(result);
4761             goto release ;
4762         }
4763         if (ifx) {
4764             genIfxJump (ifx,"c");
4765             goto release ;
4766         }
4767         /* if the result is used in an arithmetic operation
4768         then put the result in place */
4769         pic14_outBitC(result);
4770     } else {
4771       
4772       gencjne(left,right,result,ifx);
4773 /*
4774       if(ifx) 
4775         gencjne(left,right,newiTempLabel(NULL));
4776       else {
4777         if(IC_TRUE(ifx)->key)
4778           gencjne(left,right,IC_TRUE(ifx)->key);
4779         else
4780           gencjne(left,right,IC_FALSE(ifx)->key);
4781         ifx->generated = 1;
4782         goto release ;
4783       }
4784       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4785         aopPut(AOP(result),"a",0);
4786         goto release ;
4787       }
4788
4789       if (ifx) {
4790         genIfxJump (ifx,"a");
4791         goto release ;
4792       }
4793 */
4794       /* if the result is used in an arithmetic operation
4795          then put the result in place */
4796 /*
4797       if (AOP_TYPE(result) != AOP_CRY) 
4798         pic14_outAcc(result);
4799 */
4800       /* leave the result in acc */
4801     }
4802
4803 release:
4804     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4805     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4806     freeAsmop(result,NULL,ic,TRUE);
4807 }
4808
4809 /*-----------------------------------------------------------------*/
4810 /* ifxForOp - returns the icode containing the ifx for operand     */
4811 /*-----------------------------------------------------------------*/
4812 static iCode *ifxForOp ( operand *op, iCode *ic )
4813 {
4814     /* if true symbol then needs to be assigned */
4815     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4816     if (IS_TRUE_SYMOP(op))
4817         return NULL ;
4818
4819     /* if this has register type condition and
4820     the next instruction is ifx with the same operand
4821     and live to of the operand is upto the ifx only then */
4822     if (ic->next &&
4823         ic->next->op == IFX &&
4824         IC_COND(ic->next)->key == op->key &&
4825         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4826         return ic->next;
4827
4828     if (ic->next &&
4829         ic->next->op == IFX &&
4830         IC_COND(ic->next)->key == op->key) {
4831       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4832       return ic->next;
4833     }
4834
4835     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4836     if (ic->next &&
4837         ic->next->op == IFX)
4838       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4839
4840     if (ic->next &&
4841         ic->next->op == IFX &&
4842         IC_COND(ic->next)->key == op->key) {
4843       DEBUGpic14_emitcode ("; "," key is okay");
4844       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4845                            OP_SYMBOL(op)->liveTo,
4846                            ic->next->seq);
4847     }
4848
4849
4850     return NULL;
4851 }
4852 /*-----------------------------------------------------------------*/
4853 /* genAndOp - for && operation                                     */
4854 /*-----------------------------------------------------------------*/
4855 static void genAndOp (iCode *ic)
4856 {
4857     operand *left,*right, *result;
4858     symbol *tlbl;
4859
4860     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4861     /* note here that && operations that are in an
4862     if statement are taken away by backPatchLabels
4863     only those used in arthmetic operations remain */
4864     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4865     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4866     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4867
4868     /* if both are bit variables */
4869     if (AOP_TYPE(left) == AOP_CRY &&
4870         AOP_TYPE(right) == AOP_CRY ) {
4871         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4872         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4873         pic14_outBitC(result);
4874     } else {
4875         tlbl = newiTempLabel(NULL);
4876         pic14_toBoolean(left);    
4877         pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
4878         pic14_toBoolean(right);
4879         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4880         pic14_outBitAcc(result);
4881     }
4882
4883     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4884     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4885     freeAsmop(result,NULL,ic,TRUE);
4886 }
4887
4888
4889 /*-----------------------------------------------------------------*/
4890 /* genOrOp - for || operation                                      */
4891 /*-----------------------------------------------------------------*/
4892 /*
4893   tsd pic port -
4894   modified this code, but it doesn't appear to ever get called
4895 */
4896
4897 static void genOrOp (iCode *ic)
4898 {
4899     operand *left,*right, *result;
4900     symbol *tlbl;
4901
4902     /* note here that || operations that are in an
4903     if statement are taken away by backPatchLabels
4904     only those used in arthmetic operations remain */
4905     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4906     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4907     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4908     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4909
4910     DEBUGpic14_AopType(__LINE__,left,right,result);
4911
4912     /* if both are bit variables */
4913     if (AOP_TYPE(left) == AOP_CRY &&
4914         AOP_TYPE(right) == AOP_CRY ) {
4915       pic14_emitcode("clrc","");
4916       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
4917                AOP(left)->aopu.aop_dir,
4918                AOP(left)->aopu.aop_dir);
4919       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4920                AOP(right)->aopu.aop_dir,
4921                AOP(right)->aopu.aop_dir);
4922       pic14_emitcode("setc","");
4923
4924     } else {
4925         tlbl = newiTempLabel(NULL);
4926         pic14_toBoolean(left);
4927         emitSKPZ;
4928         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4929         pic14_toBoolean(right);
4930         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4931
4932         pic14_outBitAcc(result);
4933     }
4934
4935     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4936     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4937     freeAsmop(result,NULL,ic,TRUE);            
4938 }
4939
4940 /*-----------------------------------------------------------------*/
4941 /* isLiteralBit - test if lit == 2^n                               */
4942 /*-----------------------------------------------------------------*/
4943 static int isLiteralBit(unsigned long lit)
4944 {
4945     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4946     0x100L,0x200L,0x400L,0x800L,
4947     0x1000L,0x2000L,0x4000L,0x8000L,
4948     0x10000L,0x20000L,0x40000L,0x80000L,
4949     0x100000L,0x200000L,0x400000L,0x800000L,
4950     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4951     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4952     int idx;
4953     
4954     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4955     for(idx = 0; idx < 32; idx++)
4956         if(lit == pw[idx])
4957             return idx+1;
4958     return 0;
4959 }
4960
4961 /*-----------------------------------------------------------------*/
4962 /* continueIfTrue -                                                */
4963 /*-----------------------------------------------------------------*/
4964 static void continueIfTrue (iCode *ic)
4965 {
4966     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4967     if(IC_TRUE(ic))
4968         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4969     ic->generated = 1;
4970 }
4971
4972 /*-----------------------------------------------------------------*/
4973 /* jmpIfTrue -                                                     */
4974 /*-----------------------------------------------------------------*/
4975 static void jumpIfTrue (iCode *ic)
4976 {
4977     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4978     if(!IC_TRUE(ic))
4979         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4980     ic->generated = 1;
4981 }
4982
4983 /*-----------------------------------------------------------------*/
4984 /* jmpTrueOrFalse -                                                */
4985 /*-----------------------------------------------------------------*/
4986 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
4987 {
4988     // ugly but optimized by peephole
4989     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4990     if(IC_TRUE(ic)){
4991         symbol *nlbl = newiTempLabel(NULL);
4992         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
4993         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4994         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4995         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
4996     }
4997     else{
4998         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4999         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5000     }
5001     ic->generated = 1;
5002 }
5003
5004 /*-----------------------------------------------------------------*/
5005 /* genAnd  - code for and                                          */
5006 /*-----------------------------------------------------------------*/
5007 static void genAnd (iCode *ic, iCode *ifx)
5008 {
5009   operand *left, *right, *result;
5010   int size, offset=0;  
5011   unsigned long lit = 0L;
5012   int bytelit = 0;
5013   resolvedIfx rIfx;
5014
5015
5016   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5017   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5018   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5019   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5020
5021   resolveIfx(&rIfx,ifx);
5022
5023   /* if left is a literal & right is not then exchange them */
5024   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5025       AOP_NEEDSACC(left)) {
5026     operand *tmp = right ;
5027     right = left;
5028     left = tmp;
5029   }
5030
5031   /* if result = right then exchange them */
5032   if(pic14_sameRegs(AOP(result),AOP(right))){
5033     operand *tmp = right ;
5034     right = left;
5035     left = tmp;
5036   }
5037
5038   /* if right is bit then exchange them */
5039   if (AOP_TYPE(right) == AOP_CRY &&
5040       AOP_TYPE(left) != AOP_CRY){
5041     operand *tmp = right ;
5042     right = left;
5043     left = tmp;
5044   }
5045   if(AOP_TYPE(right) == AOP_LIT)
5046     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5047
5048   size = AOP_SIZE(result);
5049
5050   DEBUGpic14_AopType(__LINE__,left,right,result);
5051
5052   // if(bit & yy)
5053   // result = bit & yy;
5054   if (AOP_TYPE(left) == AOP_CRY){
5055     // c = bit & literal;
5056     if(AOP_TYPE(right) == AOP_LIT){
5057       if(lit & 1) {
5058         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5059           // no change
5060           goto release;
5061         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5062       } else {
5063         // bit(result) = 0;
5064         if(size && (AOP_TYPE(result) == AOP_CRY)){
5065           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5066           goto release;
5067         }
5068         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5069           jumpIfTrue(ifx);
5070           goto release;
5071         }
5072         pic14_emitcode("clr","c");
5073       }
5074     } else {
5075       if (AOP_TYPE(right) == AOP_CRY){
5076         // c = bit & bit;
5077         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5078         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5079       } else {
5080         // c = bit & val;
5081         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5082         // c = lsb
5083         pic14_emitcode("rrc","a");
5084         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5085       }
5086     }
5087     // bit = c
5088     // val = c
5089     if(size)
5090       pic14_outBitC(result);
5091     // if(bit & ...)
5092     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5093       genIfxJump(ifx, "c");           
5094     goto release ;
5095   }
5096
5097   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5098   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5099   if((AOP_TYPE(right) == AOP_LIT) &&
5100      (AOP_TYPE(result) == AOP_CRY) &&
5101      (AOP_TYPE(left) != AOP_CRY)){
5102     int posbit = isLiteralBit(lit);
5103     /* left &  2^n */
5104     if(posbit){
5105       posbit--;
5106       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5107       // bit = left & 2^n
5108       if(size)
5109         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5110       // if(left &  2^n)
5111       else{
5112         if(ifx){
5113 /*
5114           if(IC_TRUE(ifx)) {
5115             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5116             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
5117           } else {
5118             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5119             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
5120           }
5121 */
5122           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5123                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5124           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5125           
5126           ifx->generated = 1;
5127         }
5128         goto release;
5129       }
5130     } else {
5131       symbol *tlbl = newiTempLabel(NULL);
5132       int sizel = AOP_SIZE(left);
5133       if(size)
5134         pic14_emitcode("setb","c");
5135       while(sizel--){
5136         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5137           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5138           // byte ==  2^n ?
5139           if((posbit = isLiteralBit(bytelit)) != 0)
5140             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5141           else{
5142             if(bytelit != 0x0FFL)
5143               pic14_emitcode("anl","a,%s",
5144                              aopGet(AOP(right),offset,FALSE,TRUE));
5145             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5146           }
5147         }
5148         offset++;
5149       }
5150       // bit = left & literal
5151       if(size){
5152         pic14_emitcode("clr","c");
5153         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5154       }
5155       // if(left & literal)
5156       else{
5157         if(ifx)
5158           jmpTrueOrFalse(ifx, tlbl);
5159         goto release ;
5160       }
5161     }
5162     pic14_outBitC(result);
5163     goto release ;
5164   }
5165
5166   /* if left is same as result */
5167   if(pic14_sameRegs(AOP(result),AOP(left))){
5168     int know_W = -1;
5169     for(;size--; offset++,lit>>=8) {
5170       if(AOP_TYPE(right) == AOP_LIT){
5171         switch(lit & 0xff) {
5172         case 0x00:
5173           /*  and'ing with 0 has clears the result */
5174           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5175           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5176           break;
5177         case 0xff:
5178           /* and'ing with 0xff is a nop when the result and left are the same */
5179           break;
5180
5181         default:
5182           {
5183             int p = my_powof2( (~lit) & 0xff );
5184             if(p>=0) {
5185               /* only one bit is set in the literal, so use a bcf instruction */
5186               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5187               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5188
5189             } else {
5190               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5191               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5192               if(know_W != (lit&0xff))
5193                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5194               know_W = lit &0xff;
5195               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5196             }
5197           }    
5198         }
5199       } else {
5200         if (AOP_TYPE(left) == AOP_ACC) {
5201           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5202         } else {                    
5203           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5204           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5205
5206         }
5207       }
5208     }
5209
5210   } else {
5211     // left & result in different registers
5212     if(AOP_TYPE(result) == AOP_CRY){
5213       // result = bit
5214       // if(size), result in bit
5215       // if(!size && ifx), conditional oper: if(left & right)
5216       symbol *tlbl = newiTempLabel(NULL);
5217       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5218       if(size)
5219         pic14_emitcode("setb","c");
5220       while(sizer--){
5221         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5222         pic14_emitcode("anl","a,%s",
5223                        aopGet(AOP(left),offset,FALSE,FALSE));
5224         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5225         offset++;
5226       }
5227       if(size){
5228         CLRC;
5229         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5230         pic14_outBitC(result);
5231       } else if(ifx)
5232         jmpTrueOrFalse(ifx, tlbl);
5233     } else {
5234       for(;(size--);offset++) {
5235         // normal case
5236         // result = left & right
5237         if(AOP_TYPE(right) == AOP_LIT){
5238           int t = (lit >> (offset*8)) & 0x0FFL;
5239           switch(t) { 
5240           case 0x00:
5241             pic14_emitcode("clrf","%s",
5242                            aopGet(AOP(result),offset,FALSE,FALSE));
5243             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5244             break;
5245           case 0xff:
5246             pic14_emitcode("movf","%s,w",
5247                            aopGet(AOP(left),offset,FALSE,FALSE));
5248             pic14_emitcode("movwf","%s",
5249                            aopGet(AOP(result),offset,FALSE,FALSE));
5250             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5251             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5252             break;
5253           default:
5254             pic14_emitcode("movlw","0x%x",t);
5255             pic14_emitcode("andwf","%s,w",
5256                            aopGet(AOP(left),offset,FALSE,FALSE));
5257             pic14_emitcode("movwf","%s",
5258                            aopGet(AOP(result),offset,FALSE,FALSE));
5259               
5260             emitpcode(POC_MOVLW, popGetLit(t));
5261             emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5262             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5263           }
5264           continue;
5265         }
5266
5267         if (AOP_TYPE(left) == AOP_ACC) {
5268           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5269           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5270         } else {
5271           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5272           pic14_emitcode("andwf","%s,w",
5273                          aopGet(AOP(left),offset,FALSE,FALSE));
5274           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5275           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5276         }
5277         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5278         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5279       }
5280     }
5281   }
5282
5283   release :
5284     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5285   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5286   freeAsmop(result,NULL,ic,TRUE);     
5287 }
5288
5289 /*-----------------------------------------------------------------*/
5290 /* genOr  - code for or                                            */
5291 /*-----------------------------------------------------------------*/
5292 static void genOr (iCode *ic, iCode *ifx)
5293 {
5294     operand *left, *right, *result;
5295     int size, offset=0;
5296     unsigned long lit = 0L;
5297
5298     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5299
5300     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5301     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5302     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5303
5304     DEBUGpic14_AopType(__LINE__,left,right,result);
5305
5306     /* if left is a literal & right is not then exchange them */
5307     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5308         AOP_NEEDSACC(left)) {
5309         operand *tmp = right ;
5310         right = left;
5311         left = tmp;
5312     }
5313
5314     /* if result = right then exchange them */
5315     if(pic14_sameRegs(AOP(result),AOP(right))){
5316         operand *tmp = right ;
5317         right = left;
5318         left = tmp;
5319     }
5320
5321     /* if right is bit then exchange them */
5322     if (AOP_TYPE(right) == AOP_CRY &&
5323         AOP_TYPE(left) != AOP_CRY){
5324         operand *tmp = right ;
5325         right = left;
5326         left = tmp;
5327     }
5328
5329     DEBUGpic14_AopType(__LINE__,left,right,result);
5330
5331     if(AOP_TYPE(right) == AOP_LIT)
5332         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5333
5334     size = AOP_SIZE(result);
5335
5336     // if(bit | yy)
5337     // xx = bit | yy;
5338     if (AOP_TYPE(left) == AOP_CRY){
5339         if(AOP_TYPE(right) == AOP_LIT){
5340             // c = bit & literal;
5341             if(lit){
5342                 // lit != 0 => result = 1
5343                 if(AOP_TYPE(result) == AOP_CRY){
5344                   if(size)
5345                     emitpcode(POC_BSF, popGet(AOP(result),0));
5346                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5347                   //     AOP(result)->aopu.aop_dir,
5348                   //     AOP(result)->aopu.aop_dir);
5349                     else if(ifx)
5350                         continueIfTrue(ifx);
5351                     goto release;
5352                 }
5353             } else {
5354                 // lit == 0 => result = left
5355                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5356                     goto release;
5357                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5358             }
5359         } else {
5360             if (AOP_TYPE(right) == AOP_CRY){
5361               if(pic14_sameRegs(AOP(result),AOP(left))){
5362                 // c = bit | bit;
5363                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5364                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5365                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5366
5367                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5368                          AOP(result)->aopu.aop_dir,
5369                          AOP(result)->aopu.aop_dir);
5370                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5371                          AOP(right)->aopu.aop_dir,
5372                          AOP(right)->aopu.aop_dir);
5373                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5374                          AOP(result)->aopu.aop_dir,
5375                          AOP(result)->aopu.aop_dir);
5376               } else {
5377                 if( AOP_TYPE(result) == AOP_ACC) {
5378                   emitpcode(POC_MOVLW, popGetLit(0));
5379                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5380                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5381                   emitpcode(POC_MOVLW, popGetLit(1));
5382
5383                 } else {
5384
5385                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5386                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5387                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5388                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5389
5390                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5391                                  AOP(result)->aopu.aop_dir,
5392                                  AOP(result)->aopu.aop_dir);
5393                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5394                                  AOP(right)->aopu.aop_dir,
5395                                  AOP(right)->aopu.aop_dir);
5396                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5397                                  AOP(left)->aopu.aop_dir,
5398                                  AOP(left)->aopu.aop_dir);
5399                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5400                                  AOP(result)->aopu.aop_dir,
5401                                  AOP(result)->aopu.aop_dir);
5402                 }
5403               }
5404             } else {
5405                 // c = bit | val;
5406                 symbol *tlbl = newiTempLabel(NULL);
5407                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5408
5409
5410                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5411                 if( AOP_TYPE(right) == AOP_ACC) {
5412                   emitpcode(POC_IORLW, popGetLit(0));
5413                   emitSKPNZ;
5414                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5415                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5416                 }
5417
5418
5419
5420                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5421                     pic14_emitcode(";XXX setb","c");
5422                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5423                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5424                 pic14_toBoolean(right);
5425                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5426                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5427                     jmpTrueOrFalse(ifx, tlbl);
5428                     goto release;
5429                 } else {
5430                     CLRC;
5431                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5432                 }
5433             }
5434         }
5435         // bit = c
5436         // val = c
5437         if(size)
5438             pic14_outBitC(result);
5439         // if(bit | ...)
5440         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5441             genIfxJump(ifx, "c");           
5442         goto release ;
5443     }
5444
5445     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5446     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5447     if((AOP_TYPE(right) == AOP_LIT) &&
5448        (AOP_TYPE(result) == AOP_CRY) &&
5449        (AOP_TYPE(left) != AOP_CRY)){
5450         if(lit){
5451           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5452             // result = 1
5453             if(size)
5454                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5455             else 
5456                 continueIfTrue(ifx);
5457             goto release;
5458         } else {
5459           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5460             // lit = 0, result = boolean(left)
5461             if(size)
5462                 pic14_emitcode(";XXX setb","c");
5463             pic14_toBoolean(right);
5464             if(size){
5465                 symbol *tlbl = newiTempLabel(NULL);
5466                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5467                 CLRC;
5468                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5469             } else {
5470                 genIfxJump (ifx,"a");
5471                 goto release;
5472             }
5473         }
5474         pic14_outBitC(result);
5475         goto release ;
5476     }
5477
5478     /* if left is same as result */
5479     if(pic14_sameRegs(AOP(result),AOP(left))){
5480       int know_W = -1;
5481       for(;size--; offset++,lit>>=8) {
5482         if(AOP_TYPE(right) == AOP_LIT){
5483           if((lit & 0xff) == 0)
5484             /*  or'ing with 0 has no effect */
5485             continue;
5486           else {
5487             int p = my_powof2(lit & 0xff);
5488             if(p>=0) {
5489               /* only one bit is set in the literal, so use a bsf instruction */
5490               emitpcode(POC_BSF,
5491                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5492             } else {
5493               if(know_W != (lit & 0xff))
5494                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5495               know_W = lit & 0xff;
5496               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5497             }
5498                     
5499           }
5500         } else {
5501           if (AOP_TYPE(left) == AOP_ACC) {
5502             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5503             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5504           } else {                  
5505             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5506             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5507
5508             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5509             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5510
5511           }
5512         }
5513       }
5514     } else {
5515         // left & result in different registers
5516         if(AOP_TYPE(result) == AOP_CRY){
5517             // result = bit
5518             // if(size), result in bit
5519             // if(!size && ifx), conditional oper: if(left | right)
5520             symbol *tlbl = newiTempLabel(NULL);
5521             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5522             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5523
5524
5525             if(size)
5526                 pic14_emitcode(";XXX setb","c");
5527             while(sizer--){
5528                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5529                 pic14_emitcode(";XXX orl","a,%s",
5530                          aopGet(AOP(left),offset,FALSE,FALSE));
5531                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5532                 offset++;
5533             }
5534             if(size){
5535                 CLRC;
5536                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5537                 pic14_outBitC(result);
5538             } else if(ifx)
5539                 jmpTrueOrFalse(ifx, tlbl);
5540         } else for(;(size--);offset++){
5541           // normal case
5542           // result = left & right
5543           if(AOP_TYPE(right) == AOP_LIT){
5544             int t = (lit >> (offset*8)) & 0x0FFL;
5545             switch(t) { 
5546             case 0x00:
5547               emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5548               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5549
5550               pic14_emitcode("movf","%s,w",
5551                        aopGet(AOP(left),offset,FALSE,FALSE));
5552               pic14_emitcode("movwf","%s",
5553                        aopGet(AOP(result),offset,FALSE,FALSE));
5554               break;
5555             default:
5556               emitpcode(POC_MOVLW,  popGetLit(t));
5557               emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5558               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5559
5560               pic14_emitcode("movlw","0x%x",t);
5561               pic14_emitcode("iorwf","%s,w",
5562                        aopGet(AOP(left),offset,FALSE,FALSE));
5563               pic14_emitcode("movwf","%s",
5564                        aopGet(AOP(result),offset,FALSE,FALSE));
5565               
5566             }
5567             continue;
5568           }
5569
5570           // faster than result <- left, anl result,right
5571           // and better if result is SFR
5572           if (AOP_TYPE(left) == AOP_ACC) {
5573             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5574             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5575           } else {
5576             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5577             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5578
5579             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5580             pic14_emitcode("iorwf","%s,w",
5581                      aopGet(AOP(left),offset,FALSE,FALSE));
5582           }
5583           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5584           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5585         }
5586     }
5587
5588 release :
5589     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5590     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5591     freeAsmop(result,NULL,ic,TRUE);     
5592 }
5593
5594 /*-----------------------------------------------------------------*/
5595 /* genXor - code for xclusive or                                   */
5596 /*-----------------------------------------------------------------*/
5597 static void genXor (iCode *ic, iCode *ifx)
5598 {
5599   operand *left, *right, *result;
5600   int size, offset=0;
5601   unsigned long lit = 0L;
5602
5603   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5604
5605   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5606   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5607   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5608
5609   /* if left is a literal & right is not ||
5610      if left needs acc & right does not */
5611   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5612       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5613     operand *tmp = right ;
5614     right = left;
5615     left = tmp;
5616   }
5617
5618   /* if result = right then exchange them */
5619   if(pic14_sameRegs(AOP(result),AOP(right))){
5620     operand *tmp = right ;
5621     right = left;
5622     left = tmp;
5623   }
5624
5625   /* if right is bit then exchange them */
5626   if (AOP_TYPE(right) == AOP_CRY &&
5627       AOP_TYPE(left) != AOP_CRY){
5628     operand *tmp = right ;
5629     right = left;
5630     left = tmp;
5631   }
5632   if(AOP_TYPE(right) == AOP_LIT)
5633     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5634
5635   size = AOP_SIZE(result);
5636
5637   // if(bit ^ yy)
5638   // xx = bit ^ yy;
5639   if (AOP_TYPE(left) == AOP_CRY){
5640     if(AOP_TYPE(right) == AOP_LIT){
5641       // c = bit & literal;
5642       if(lit>>1){
5643         // lit>>1  != 0 => result = 1
5644         if(AOP_TYPE(result) == AOP_CRY){
5645           if(size)
5646             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5647             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5648           else if(ifx)
5649             continueIfTrue(ifx);
5650           goto release;
5651         }
5652         pic14_emitcode("setb","c");
5653       } else{
5654         // lit == (0 or 1)
5655         if(lit == 0){
5656           // lit == 0, result = left
5657           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5658             goto release;
5659           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5660         } else{
5661           // lit == 1, result = not(left)
5662           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5663             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5664             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5665             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5666             goto release;
5667           } else {
5668             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5669             pic14_emitcode("cpl","c");
5670           }
5671         }
5672       }
5673
5674     } else {
5675       // right != literal
5676       symbol *tlbl = newiTempLabel(NULL);
5677       if (AOP_TYPE(right) == AOP_CRY){
5678         // c = bit ^ bit;
5679         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5680       }
5681       else{
5682         int sizer = AOP_SIZE(right);
5683         // c = bit ^ val
5684         // if val>>1 != 0, result = 1
5685         pic14_emitcode("setb","c");
5686         while(sizer){
5687           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5688           if(sizer == 1)
5689             // test the msb of the lsb
5690             pic14_emitcode("anl","a,#0xfe");
5691           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5692           sizer--;
5693         }
5694         // val = (0,1)
5695         pic14_emitcode("rrc","a");
5696       }
5697       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5698       pic14_emitcode("cpl","c");
5699       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5700     }
5701     // bit = c
5702     // val = c
5703     if(size)
5704       pic14_outBitC(result);
5705     // if(bit | ...)
5706     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5707       genIfxJump(ifx, "c");           
5708     goto release ;
5709   }
5710
5711   if(pic14_sameRegs(AOP(result),AOP(left))){
5712     /* if left is same as result */
5713     for(;size--; offset++) {
5714       if(AOP_TYPE(right) == AOP_LIT){
5715         int t  = (lit >> (offset*8)) & 0x0FFL;
5716         if(t == 0x00L)
5717           continue;
5718         else
5719           if (IS_AOP_PREG(left)) {
5720             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5721             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5722             aopPut(AOP(result),"a",offset);
5723           } else {
5724             emitpcode(POC_MOVLW, popGetLit(t));
5725             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5726             pic14_emitcode("xrl","%s,%s",
5727                            aopGet(AOP(left),offset,FALSE,TRUE),
5728                            aopGet(AOP(right),offset,FALSE,FALSE));
5729           }
5730       } else {
5731         if (AOP_TYPE(left) == AOP_ACC)
5732           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5733         else {
5734           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5735           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5736 /*
5737           if (IS_AOP_PREG(left)) {
5738             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5739             aopPut(AOP(result),"a",offset);
5740           } else
5741             pic14_emitcode("xrl","%s,a",
5742                            aopGet(AOP(left),offset,FALSE,TRUE));
5743 */
5744         }
5745       }
5746     }
5747   } else {
5748     // left & result in different registers
5749     if(AOP_TYPE(result) == AOP_CRY){
5750       // result = bit
5751       // if(size), result in bit
5752       // if(!size && ifx), conditional oper: if(left ^ right)
5753       symbol *tlbl = newiTempLabel(NULL);
5754       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5755       if(size)
5756         pic14_emitcode("setb","c");
5757       while(sizer--){
5758         if((AOP_TYPE(right) == AOP_LIT) &&
5759            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5760           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5761         } else {
5762           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5763           pic14_emitcode("xrl","a,%s",
5764                          aopGet(AOP(left),offset,FALSE,FALSE));
5765         }
5766         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5767         offset++;
5768       }
5769       if(size){
5770         CLRC;
5771         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5772         pic14_outBitC(result);
5773       } else if(ifx)
5774         jmpTrueOrFalse(ifx, tlbl);
5775     } else for(;(size--);offset++){
5776       // normal case
5777       // result = left & right
5778       if(AOP_TYPE(right) == AOP_LIT){
5779         int t = (lit >> (offset*8)) & 0x0FFL;
5780         switch(t) { 
5781         case 0x00:
5782           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5783           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5784           pic14_emitcode("movf","%s,w",
5785                          aopGet(AOP(left),offset,FALSE,FALSE));
5786           pic14_emitcode("movwf","%s",
5787                          aopGet(AOP(result),offset,FALSE,FALSE));
5788           break;
5789         case 0xff:
5790           emitpcode(POC_COMFW,popGet(AOP(left),offset));
5791           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5792           pic14_emitcode("comf","%s,w",
5793                          aopGet(AOP(left),offset,FALSE,FALSE));
5794           pic14_emitcode("movwf","%s",
5795                          aopGet(AOP(result),offset,FALSE,FALSE));
5796           break;
5797         default:
5798           emitpcode(POC_MOVLW, popGetLit(t));
5799           emitpcode(POC_XORFW,popGet(AOP(left),offset));
5800           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5801           pic14_emitcode("movlw","0x%x",t);
5802           pic14_emitcode("xorwf","%s,w",
5803                          aopGet(AOP(left),offset,FALSE,FALSE));
5804           pic14_emitcode("movwf","%s",
5805                          aopGet(AOP(result),offset,FALSE,FALSE));
5806
5807         }
5808         continue;
5809       }
5810
5811       // faster than result <- left, anl result,right
5812       // and better if result is SFR
5813       if (AOP_TYPE(left) == AOP_ACC) {
5814         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5815         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5816       } else {
5817         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5818         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5819         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5820         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5821       }
5822       if ( AOP_TYPE(result) != AOP_ACC){
5823         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5824         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5825       }
5826     }
5827   }
5828
5829   release :
5830     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5831   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5832   freeAsmop(result,NULL,ic,TRUE);     
5833 }
5834
5835 /*-----------------------------------------------------------------*/
5836 /* genInline - write the inline code out                           */
5837 /*-----------------------------------------------------------------*/
5838 static void genInline (iCode *ic)
5839 {
5840     char *buffer, *bp, *bp1;
5841     
5842     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5843
5844     _G.inLine += (!options.asmpeep);
5845
5846     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5847     strcpy(buffer,IC_INLINE(ic));
5848
5849     /* emit each line as a code */
5850     while (*bp) {
5851         if (*bp == '\n') {
5852             *bp++ = '\0';
5853             pic14_emitcode(bp1,"");
5854             bp1 = bp;
5855         } else {
5856             if (*bp == ':') {
5857                 bp++;
5858                 *bp = '\0';
5859                 bp++;
5860                 pic14_emitcode(bp1,"");
5861                 bp1 = bp;
5862             } else
5863                 bp++;
5864         }
5865     }
5866     if (bp1 != bp)
5867         pic14_emitcode(bp1,"");
5868     /*     pic14_emitcode("",buffer); */
5869     _G.inLine -= (!options.asmpeep);
5870 }
5871
5872 /*-----------------------------------------------------------------*/
5873 /* genRRC - rotate right with carry                                */
5874 /*-----------------------------------------------------------------*/
5875 static void genRRC (iCode *ic)
5876 {
5877   operand *left , *result ;
5878   int size, offset = 0, same;
5879
5880   /* rotate right with carry */
5881   left = IC_LEFT(ic);
5882   result=IC_RESULT(ic);
5883   aopOp (left,ic,FALSE);
5884   aopOp (result,ic,FALSE);
5885
5886   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5887
5888   same = pic14_sameRegs(AOP(result),AOP(left));
5889
5890   size = AOP_SIZE(result);    
5891
5892   /* get the lsb and put it into the carry */
5893   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
5894
5895   offset = 0 ;
5896
5897   while(size--) {
5898
5899     if(same) {
5900       emitpcode(POC_RRF, popGet(AOP(left),offset));
5901     } else {
5902       emitpcode(POC_RRFW, popGet(AOP(left),offset));
5903       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5904     }
5905
5906     offset++;
5907   }
5908
5909   freeAsmop(left,NULL,ic,TRUE);
5910   freeAsmop(result,NULL,ic,TRUE);
5911 }
5912
5913 /*-----------------------------------------------------------------*/
5914 /* genRLC - generate code for rotate left with carry               */
5915 /*-----------------------------------------------------------------*/
5916 static void genRLC (iCode *ic)
5917 {    
5918   operand *left , *result ;
5919   int size, offset = 0;
5920   int same;
5921
5922   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5923   /* rotate right with carry */
5924   left = IC_LEFT(ic);
5925   result=IC_RESULT(ic);
5926   aopOp (left,ic,FALSE);
5927   aopOp (result,ic,FALSE);
5928
5929   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5930
5931   same = pic14_sameRegs(AOP(result),AOP(left));
5932
5933   /* move it to the result */
5934   size = AOP_SIZE(result);    
5935
5936   /* get the msb and put it into the carry */
5937   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
5938
5939   offset = 0 ;
5940
5941   while(size--) {
5942
5943     if(same) {
5944       emitpcode(POC_RLF, popGet(AOP(left),offset));
5945     } else {
5946       emitpcode(POC_RLFW, popGet(AOP(left),offset));
5947       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5948     }
5949
5950     offset++;
5951   }
5952
5953
5954   freeAsmop(left,NULL,ic,TRUE);
5955   freeAsmop(result,NULL,ic,TRUE);
5956 }
5957
5958 /*-----------------------------------------------------------------*/
5959 /* genGetHbit - generates code get highest order bit               */
5960 /*-----------------------------------------------------------------*/
5961 static void genGetHbit (iCode *ic)
5962 {
5963     operand *left, *result;
5964     left = IC_LEFT(ic);
5965     result=IC_RESULT(ic);
5966     aopOp (left,ic,FALSE);
5967     aopOp (result,ic,FALSE);
5968
5969     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5970     /* get the highest order byte into a */
5971     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5972     if(AOP_TYPE(result) == AOP_CRY){
5973         pic14_emitcode("rlc","a");
5974         pic14_outBitC(result);
5975     }
5976     else{
5977         pic14_emitcode("rl","a");
5978         pic14_emitcode("anl","a,#0x01");
5979         pic14_outAcc(result);
5980     }
5981
5982
5983     freeAsmop(left,NULL,ic,TRUE);
5984     freeAsmop(result,NULL,ic,TRUE);
5985 }
5986
5987 /*-----------------------------------------------------------------*/
5988 /* AccRol - rotate left accumulator by known count                 */
5989 /*-----------------------------------------------------------------*/
5990 static void AccRol (int shCount)
5991 {
5992     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5993     shCount &= 0x0007;              // shCount : 0..7
5994     switch(shCount){
5995         case 0 :
5996             break;
5997         case 1 :
5998             pic14_emitcode("rl","a");
5999             break;
6000         case 2 :
6001             pic14_emitcode("rl","a");
6002             pic14_emitcode("rl","a");
6003             break;
6004         case 3 :
6005             pic14_emitcode("swap","a");
6006             pic14_emitcode("rr","a");
6007             break;
6008         case 4 :
6009             pic14_emitcode("swap","a");
6010             break;
6011         case 5 :
6012             pic14_emitcode("swap","a");
6013             pic14_emitcode("rl","a");
6014             break;
6015         case 6 :
6016             pic14_emitcode("rr","a");
6017             pic14_emitcode("rr","a");
6018             break;
6019         case 7 :
6020             pic14_emitcode("rr","a");
6021             break;
6022     }
6023 }
6024
6025 /*-----------------------------------------------------------------*/
6026 /* AccLsh - left shift accumulator by known count                  */
6027 /*-----------------------------------------------------------------*/
6028 static void AccLsh (int shCount)
6029 {
6030     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6031     if(shCount != 0){
6032         if(shCount == 1)
6033             pic14_emitcode("add","a,acc");
6034         else 
6035             if(shCount == 2) {
6036             pic14_emitcode("add","a,acc");
6037             pic14_emitcode("add","a,acc");
6038         } else {
6039             /* rotate left accumulator */
6040             AccRol(shCount);
6041             /* and kill the lower order bits */
6042             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6043         }
6044     }
6045 }
6046
6047 /*-----------------------------------------------------------------*/
6048 /* AccRsh - right shift accumulator by known count                 */
6049 /*-----------------------------------------------------------------*/
6050 static void AccRsh (int shCount)
6051 {
6052     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6053     if(shCount != 0){
6054         if(shCount == 1){
6055             CLRC;
6056             pic14_emitcode("rrc","a");
6057         } else {
6058             /* rotate right accumulator */
6059             AccRol(8 - shCount);
6060             /* and kill the higher order bits */
6061             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6062         }
6063     }
6064 }
6065
6066 #if 0
6067 /*-----------------------------------------------------------------*/
6068 /* AccSRsh - signed right shift accumulator by known count                 */
6069 /*-----------------------------------------------------------------*/
6070 static void AccSRsh (int shCount)
6071 {
6072     symbol *tlbl ;
6073     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6074     if(shCount != 0){
6075         if(shCount == 1){
6076             pic14_emitcode("mov","c,acc.7");
6077             pic14_emitcode("rrc","a");
6078         } else if(shCount == 2){
6079             pic14_emitcode("mov","c,acc.7");
6080             pic14_emitcode("rrc","a");
6081             pic14_emitcode("mov","c,acc.7");
6082             pic14_emitcode("rrc","a");
6083         } else {
6084             tlbl = newiTempLabel(NULL);
6085             /* rotate right accumulator */
6086             AccRol(8 - shCount);
6087             /* and kill the higher order bits */
6088             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6089             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6090             pic14_emitcode("orl","a,#0x%02x",
6091                      (unsigned char)~SRMask[shCount]);
6092             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6093         }
6094     }
6095 }
6096 #endif
6097 /*-----------------------------------------------------------------*/
6098 /* shiftR1Left2Result - shift right one byte from left to result   */
6099 /*-----------------------------------------------------------------*/
6100 static void shiftR1Left2ResultSigned (operand *left, int offl,
6101                                 operand *result, int offr,
6102                                 int shCount)
6103 {
6104   int same;
6105
6106   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6107
6108   same = (left == result) || (AOP(left) == AOP(result));
6109
6110   switch(shCount) {
6111   case 1:
6112     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6113     if(same) 
6114       emitpcode(POC_RRF, popGet(AOP(result),offr));
6115     else {
6116       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6117       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6118     }
6119
6120     break;
6121
6122   default:
6123     break;
6124   }
6125 }
6126
6127 /*-----------------------------------------------------------------*/
6128 /* shiftR1Left2Result - shift right one byte from left to result   */
6129 /*-----------------------------------------------------------------*/
6130 static void shiftR1Left2Result (operand *left, int offl,
6131                                 operand *result, int offr,
6132                                 int shCount, int sign)
6133 {
6134   int same;
6135
6136   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6137
6138   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6139
6140   /* Copy the msb into the carry if signed. */
6141   if(sign) {
6142     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6143     return;
6144   }
6145
6146
6147
6148   switch(shCount) {
6149   case 1:
6150     emitCLRC;
6151     if(same) 
6152       emitpcode(POC_RRF, popGet(AOP(result),offr));
6153     else {
6154       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6155       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6156     }
6157     break;
6158   case 2:
6159     emitCLRC;
6160     if(same) {
6161       emitpcode(POC_RRF, popGet(AOP(result),offr));
6162     } else {
6163       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6164       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6165     }
6166     emitCLRC;
6167     emitpcode(POC_RRF, popGet(AOP(result),offr));
6168
6169     break;
6170   case 3:
6171     if(same) 
6172       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6173     else {
6174       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6175       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6176     }
6177
6178     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6179     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6180     emitpcode(POC_ANDLW, popGetLit(0x1f));
6181     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6182     break;
6183       
6184   case 4:
6185     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6186     emitpcode(POC_ANDLW, popGetLit(0x0f));
6187     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6188     break;
6189
6190   case 5:
6191     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6192     emitpcode(POC_ANDLW, popGetLit(0x0f));
6193     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6194     emitCLRC;
6195     emitpcode(POC_RRF, popGet(AOP(result),offr));
6196
6197     break;
6198   case 6:
6199
6200     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6201     emitpcode(POC_ANDLW, popGetLit(0x80));
6202     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6203     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6204     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6205     break;
6206
6207   case 7:
6208
6209     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6210     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6211     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6212
6213     break;
6214
6215   default:
6216     break;
6217   }
6218
6219
6220 #if 0
6221     
6222   MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6223
6224   /* shift right accumulator */
6225   if(sign)
6226     AccSRsh(shCount);
6227   else
6228     AccRsh(shCount);
6229   aopPut(AOP(result),"a",offr);
6230 #endif
6231 }
6232
6233 /*-----------------------------------------------------------------*/
6234 /* shiftL1Left2Result - shift left one byte from left to result    */
6235 /*-----------------------------------------------------------------*/
6236 static void shiftL1Left2Result (operand *left, int offl,
6237                                 operand *result, int offr, int shCount)
6238 {
6239   int same;
6240
6241   //    char *l;
6242   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6243
6244   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6245   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6246     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6247     //    MOVA(l);
6248     /* shift left accumulator */
6249     //AccLsh(shCount); // don't comment out just yet...
6250   //    aopPut(AOP(result),"a",offr);
6251
6252   switch(shCount) {
6253   case 1:
6254     /* Shift left 1 bit position */
6255     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6256     if(same) {
6257       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6258     } else {
6259       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6260       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6261     }
6262     break;
6263   case 2:
6264     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6265     emitpcode(POC_ANDLW,popGetLit(0x7e));
6266     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6267     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6268     break;
6269   case 3:
6270     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6271     emitpcode(POC_ANDLW,popGetLit(0x3e));
6272     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6273     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6274     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6275     break;
6276   case 4:
6277     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6278     emitpcode(POC_ANDLW, popGetLit(0xf0));
6279     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6280     break;
6281   case 5:
6282     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6283     emitpcode(POC_ANDLW, popGetLit(0xf0));
6284     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6285     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6286     break;
6287   case 6:
6288     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6289     emitpcode(POC_ANDLW, popGetLit(0x30));
6290     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6291     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6292     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6293     break;
6294   case 7:
6295     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6296     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6297     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6298     break;
6299
6300   default:
6301     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6302   }
6303
6304 }
6305
6306 /*-----------------------------------------------------------------*/
6307 /* movLeft2Result - move byte from left to result                  */
6308 /*-----------------------------------------------------------------*/
6309 static void movLeft2Result (operand *left, int offl,
6310                             operand *result, int offr, int sign)
6311 {
6312     char *l;
6313     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6314     if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6315         l = aopGet(AOP(left),offl,FALSE,FALSE);
6316
6317         if (*l == '@' && (IS_AOP_PREG(result))) {
6318             pic14_emitcode("mov","a,%s",l);
6319             aopPut(AOP(result),"a",offr);
6320         } else {
6321           if(!sign) {
6322             emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6323             emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6324
6325             //aopPut(AOP(result),l,offr);
6326           }else{
6327                 /* MSB sign in acc.7 ! */
6328                 if(pic14_getDataSize(left) == offl+1){
6329                     pic14_emitcode("mov","a,%s",l);
6330                     aopPut(AOP(result),"a",offr);
6331                 }
6332             }
6333         }
6334     }
6335 }
6336
6337 /*-----------------------------------------------------------------*/
6338 /* shiftL2Left2Result - shift left two bytes from left to result   */
6339 /*-----------------------------------------------------------------*/
6340 static void shiftL2Left2Result (operand *left, int offl,
6341                                 operand *result, int offr, int shCount)
6342 {
6343
6344
6345   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6346
6347   if(pic14_sameRegs(AOP(result), AOP(left))) {
6348     switch(shCount) {
6349     case 0:
6350       break;
6351     case 1:
6352     case 2:
6353     case 3:
6354
6355       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6356       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6357       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6358
6359       while(--shCount) {
6360         emitCLRC;
6361         emitpcode(POC_RLF, popGet(AOP(result),offr));
6362         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6363       }
6364
6365       break;
6366     case 4:
6367     case 5:
6368       emitpcode(POC_MOVLW, popGetLit(0x0f));
6369       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6370       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6371       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6372       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6373       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6374       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6375       if(shCount >=5) {
6376         emitpcode(POC_RLF, popGet(AOP(result),offr));
6377         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6378       }
6379       break;
6380     case 6:
6381       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6382       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6383       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6384       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6385       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6386       emitpcode(POC_ANDLW,popGetLit(0xc0));
6387       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6388       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6389       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6390       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6391       break;
6392     case 7:
6393       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6394       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6395       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6396       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6397       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6398     }
6399
6400   } else {
6401     switch(shCount) {
6402     case 0:
6403       break;
6404     case 1:
6405     case 2:
6406     case 3:
6407       /* note, use a mov/add for the shift since the mov has a
6408          chance of getting optimized out */
6409       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6410       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6411       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6412       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6413       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6414
6415       while(--shCount) {
6416         emitCLRC;
6417         emitpcode(POC_RLF, popGet(AOP(result),offr));
6418         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6419       }
6420       break;
6421
6422     case 4:
6423     case 5:
6424       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6425       emitpcode(POC_ANDLW, popGetLit(0xF0));
6426       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6427       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6428       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6429       emitpcode(POC_ANDLW, popGetLit(0xF0));
6430       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6431       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6432
6433
6434       if(shCount == 5) {
6435         emitpcode(POC_RLF, popGet(AOP(result),offr));
6436         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6437       }
6438       break;
6439     case 6:
6440       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6441       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6442       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6443       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6444
6445       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6446       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6447       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6448       emitpcode(POC_ANDLW,popGetLit(0xc0));
6449       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6450       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6451       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6452       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6453       break;
6454     case 7:
6455       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6456       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6457       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6458       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6459       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6460     }
6461   }
6462
6463 }
6464 /*-----------------------------------------------------------------*/
6465 /* shiftR2Left2Result - shift right two bytes from left to result  */
6466 /*-----------------------------------------------------------------*/
6467 static void shiftR2Left2Result (operand *left, int offl,
6468                                 operand *result, int offr,
6469                                 int shCount, int sign)
6470 {
6471   int same=0;
6472
6473   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6474   same = pic14_sameRegs(AOP(result), AOP(left));
6475
6476   if(same && ((offl + MSB16) == offr)){
6477     same=1;
6478     /* don't crash result[offr] */
6479     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6480     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6481   } else {
6482     movLeft2Result(left,offl, result, offr, 0);
6483     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6484   }
6485   /* a:x >> shCount (x = lsb(result))*/
6486 /*
6487   if(sign)
6488     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6489   else {
6490     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6491 */
6492   switch(shCount) {
6493   case 0:
6494     break;
6495   case 1:
6496   case 2:
6497   case 3:
6498     emitCLRC;
6499     if(same) {
6500       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6501       emitpcode(POC_RRF,popGet(AOP(result),offr));
6502     } else {
6503
6504       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6505       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6506       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6507       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6508     }
6509
6510     while(--shCount) {
6511       emitCLRC;
6512       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6513       emitpcode(POC_RRF,popGet(AOP(result),offr));
6514     }
6515     break;
6516   case 4:
6517   case 5:
6518     if(same) {
6519
6520       emitpcode(POC_MOVLW, popGetLit(0xf0));
6521       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6522       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6523
6524       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6525       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6526       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6527       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6528     } else {
6529       emitpcode(POC_SWAPF, popGet(AOP(left),offl));
6530       emitpcode(POC_ANDLW, popGetLit(0x0f));
6531       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6532
6533       emitpcode(POC_SWAPF, popGet(AOP(left),offl+MSB16));
6534       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6535       emitpcode(POC_ANDLW, popGetLit(0xf0));
6536       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6537       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6538     }
6539
6540     if(shCount >=5) {
6541       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6542       emitpcode(POC_RRF, popGet(AOP(result),offr));
6543     }
6544
6545     break;
6546
6547   case 6:
6548     if(same) {
6549
6550       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6551       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6552
6553       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6554       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6555       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6556       emitpcode(POC_ANDLW,popGetLit(0x03));
6557       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6558       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6559       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6560       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6561     } else {
6562       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6563       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6564       emitpcode(POC_RLFW, popGet(AOP(result),offl+MSB16));
6565       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6566       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6567       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6568       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6569       emitpcode(POC_ANDLW,popGetLit(0x03));
6570       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6571     }
6572
6573     break;
6574   case 7:
6575     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6576     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6577     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6578     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6579     emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6580   }
6581 }
6582
6583
6584 /*-----------------------------------------------------------------*/
6585 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6586 /*-----------------------------------------------------------------*/
6587 static void shiftLLeftOrResult (operand *left, int offl,
6588                                 operand *result, int offr, int shCount)
6589 {
6590     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6591     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6592     /* shift left accumulator */
6593     AccLsh(shCount);
6594     /* or with result */
6595     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6596     /* back to result */
6597     aopPut(AOP(result),"a",offr);
6598 }
6599
6600 /*-----------------------------------------------------------------*/
6601 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6602 /*-----------------------------------------------------------------*/
6603 static void shiftRLeftOrResult (operand *left, int offl,
6604                                 operand *result, int offr, int shCount)
6605 {
6606     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6607     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6608     /* shift right accumulator */
6609     AccRsh(shCount);
6610     /* or with result */
6611     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6612     /* back to result */
6613     aopPut(AOP(result),"a",offr);
6614 }
6615
6616 /*-----------------------------------------------------------------*/
6617 /* genlshOne - left shift a one byte quantity by known count       */
6618 /*-----------------------------------------------------------------*/
6619 static void genlshOne (operand *result, operand *left, int shCount)
6620 {       
6621     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6622     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6623 }
6624
6625 /*-----------------------------------------------------------------*/
6626 /* genlshTwo - left shift two bytes by known amount != 0           */
6627 /*-----------------------------------------------------------------*/
6628 static void genlshTwo (operand *result,operand *left, int shCount)
6629 {
6630     int size;
6631     
6632     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6633     size = pic14_getDataSize(result);
6634
6635     /* if shCount >= 8 */
6636     if (shCount >= 8) {
6637         shCount -= 8 ;
6638
6639         if (size > 1){
6640             if (shCount)
6641                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6642             else 
6643                 movLeft2Result(left, LSB, result, MSB16, 0);
6644         }
6645         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6646     }
6647
6648     /*  1 <= shCount <= 7 */
6649     else {  
6650         if(size == 1)
6651             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6652         else 
6653             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6654     }
6655 }
6656
6657 /*-----------------------------------------------------------------*/
6658 /* shiftLLong - shift left one long from left to result            */
6659 /* offl = LSB or MSB16                                             */
6660 /*-----------------------------------------------------------------*/
6661 static void shiftLLong (operand *left, operand *result, int offr )
6662 {
6663     char *l;
6664     int size = AOP_SIZE(result);
6665
6666     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6667     if(size >= LSB+offr){
6668         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6669         MOVA(l);
6670         pic14_emitcode("add","a,acc");
6671         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6672             size >= MSB16+offr && offr != LSB )
6673             pic14_emitcode("xch","a,%s",
6674                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6675         else        
6676             aopPut(AOP(result),"a",LSB+offr);
6677     }
6678
6679     if(size >= MSB16+offr){
6680         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6681             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6682             MOVA(l);
6683         }
6684         pic14_emitcode("rlc","a");
6685         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6686             size >= MSB24+offr && offr != LSB)
6687             pic14_emitcode("xch","a,%s",
6688                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6689         else        
6690             aopPut(AOP(result),"a",MSB16+offr);
6691     }
6692
6693     if(size >= MSB24+offr){
6694         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6695             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6696             MOVA(l);
6697         }
6698         pic14_emitcode("rlc","a");
6699         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6700             size >= MSB32+offr && offr != LSB )
6701             pic14_emitcode("xch","a,%s",
6702                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6703         else        
6704             aopPut(AOP(result),"a",MSB24+offr);
6705     }
6706
6707     if(size > MSB32+offr){
6708         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6709             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6710             MOVA(l);    
6711         }
6712         pic14_emitcode("rlc","a");
6713         aopPut(AOP(result),"a",MSB32+offr);
6714     }
6715     if(offr != LSB)
6716         aopPut(AOP(result),zero,LSB);       
6717 }
6718
6719 /*-----------------------------------------------------------------*/
6720 /* genlshFour - shift four byte by a known amount != 0             */
6721 /*-----------------------------------------------------------------*/
6722 static void genlshFour (operand *result, operand *left, int shCount)
6723 {
6724     int size;
6725
6726     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6727     size = AOP_SIZE(result);
6728
6729     /* if shifting more that 3 bytes */
6730     if (shCount >= 24 ) {
6731         shCount -= 24;
6732         if (shCount)
6733             /* lowest order of left goes to the highest
6734             order of the destination */
6735             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6736         else
6737             movLeft2Result(left, LSB, result, MSB32, 0);
6738         aopPut(AOP(result),zero,LSB);
6739         aopPut(AOP(result),zero,MSB16);
6740         aopPut(AOP(result),zero,MSB32);
6741         return;
6742     }
6743
6744     /* more than two bytes */
6745     else if ( shCount >= 16 ) {
6746         /* lower order two bytes goes to higher order two bytes */
6747         shCount -= 16;
6748         /* if some more remaining */
6749         if (shCount)
6750             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6751         else {
6752             movLeft2Result(left, MSB16, result, MSB32, 0);
6753             movLeft2Result(left, LSB, result, MSB24, 0);
6754         }
6755         aopPut(AOP(result),zero,MSB16);
6756         aopPut(AOP(result),zero,LSB);
6757         return;
6758     }    
6759
6760     /* if more than 1 byte */
6761     else if ( shCount >= 8 ) {
6762         /* lower order three bytes goes to higher order  three bytes */
6763         shCount -= 8;
6764         if(size == 2){
6765             if(shCount)
6766                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6767             else
6768                 movLeft2Result(left, LSB, result, MSB16, 0);
6769         }
6770         else{   /* size = 4 */
6771             if(shCount == 0){
6772                 movLeft2Result(left, MSB24, result, MSB32, 0);
6773                 movLeft2Result(left, MSB16, result, MSB24, 0);
6774                 movLeft2Result(left, LSB, result, MSB16, 0);
6775                 aopPut(AOP(result),zero,LSB);
6776             }
6777             else if(shCount == 1)
6778                 shiftLLong(left, result, MSB16);
6779             else{
6780                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6781                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6782                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6783                 aopPut(AOP(result),zero,LSB);
6784             }
6785         }
6786     }
6787
6788     /* 1 <= shCount <= 7 */
6789     else if(shCount <= 2){
6790         shiftLLong(left, result, LSB);
6791         if(shCount == 2)
6792             shiftLLong(result, result, LSB);
6793     }
6794     /* 3 <= shCount <= 7, optimize */
6795     else{
6796         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6797         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6798         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6799     }
6800 }
6801
6802 /*-----------------------------------------------------------------*/
6803 /* genLeftShiftLiteral - left shifting by known count              */
6804 /*-----------------------------------------------------------------*/
6805 static void genLeftShiftLiteral (operand *left,
6806                                  operand *right,
6807                                  operand *result,
6808                                  iCode *ic)
6809 {    
6810     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6811     int size;
6812
6813     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6814     freeAsmop(right,NULL,ic,TRUE);
6815
6816     aopOp(left,ic,FALSE);
6817     aopOp(result,ic,FALSE);
6818
6819     size = getSize(operandType(result));
6820
6821 #if VIEW_SIZE
6822     pic14_emitcode("; shift left ","result %d, left %d",size,
6823              AOP_SIZE(left));
6824 #endif
6825
6826     /* I suppose that the left size >= result size */
6827     if(shCount == 0){
6828         while(size--){
6829             movLeft2Result(left, size, result, size, 0);
6830         }
6831     }
6832
6833     else if(shCount >= (size * 8))
6834         while(size--)
6835             aopPut(AOP(result),zero,size);
6836     else{
6837         switch (size) {
6838             case 1:
6839                 genlshOne (result,left,shCount);
6840                 break;
6841
6842             case 2:
6843             case 3:
6844                 genlshTwo (result,left,shCount);
6845                 break;
6846
6847             case 4:
6848                 genlshFour (result,left,shCount);
6849                 break;
6850         }
6851     }
6852     freeAsmop(left,NULL,ic,TRUE);
6853     freeAsmop(result,NULL,ic,TRUE);
6854 }
6855
6856 /*-----------------------------------------------------------------*
6857  * genMultiAsm - repeat assembly instruction for size of register.
6858  * if endian == 1, then the high byte (i.e base address + size of 
6859  * register) is used first else the low byte is used first;
6860  *-----------------------------------------------------------------*/
6861 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
6862 {
6863
6864   int offset = 0;
6865
6866   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6867
6868   if(!reg)
6869     return;
6870
6871   if(!endian) {
6872     endian = 1;
6873   } else {
6874     endian = -1;
6875     offset = size-1;
6876   }
6877
6878   while(size--) {
6879     emitpcode(poc,    popGet(AOP(reg),offset));
6880     offset += endian;
6881   }
6882
6883 }
6884 /*-----------------------------------------------------------------*/
6885 /* genLeftShift - generates code for left shifting                 */
6886 /*-----------------------------------------------------------------*/
6887 static void genLeftShift (iCode *ic)
6888 {
6889     operand *left,*right, *result;
6890     int size, offset;
6891     char *l;
6892     symbol *tlbl , *tlbl1;
6893
6894     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6895
6896     right = IC_RIGHT(ic);
6897     left  = IC_LEFT(ic);
6898     result = IC_RESULT(ic);
6899
6900     aopOp(right,ic,FALSE);
6901
6902     /* if the shift count is known then do it 
6903     as efficiently as possible */
6904     if (AOP_TYPE(right) == AOP_LIT) {
6905         genLeftShiftLiteral (left,right,result,ic);
6906         return ;
6907     }
6908
6909     /* shift count is unknown then we have to form 
6910     a loop get the loop count in B : Note: we take
6911     only the lower order byte since shifting
6912     more that 32 bits make no sense anyway, ( the
6913     largest size of an object can be only 32 bits ) */  
6914
6915     
6916     aopOp(left,ic,FALSE);
6917     aopOp(result,ic,FALSE);
6918
6919     /* now move the left to the result if they are not the
6920     same */
6921     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
6922         AOP_SIZE(result) > 1) {
6923
6924         size = AOP_SIZE(result);
6925         offset=0;
6926         while (size--) {
6927             l = aopGet(AOP(left),offset,FALSE,TRUE);
6928             if (*l == '@' && (IS_AOP_PREG(result))) {
6929
6930                 pic14_emitcode("mov","a,%s",l);
6931                 aopPut(AOP(result),"a",offset);
6932             } else
6933                 aopPut(AOP(result),l,offset);
6934             offset++;
6935         }
6936     }
6937
6938     size = AOP_SIZE(result);
6939
6940     /* if it is only one byte then */
6941     if (size == 1) {
6942       if(optimized_for_speed) {
6943         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
6944         emitpcode(POC_ANDLW,  popGetLit(0xf0));
6945         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
6946         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
6947         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
6948         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
6949         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
6950         emitpcode(POC_RLFW,   popGet(AOP(result),0));
6951         emitpcode(POC_ANDLW,  popGetLit(0xfe));
6952         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
6953         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
6954         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
6955       } else {
6956
6957         tlbl = newiTempLabel(NULL);
6958         if (!pic14_sameRegs(AOP(left),AOP(result))) {
6959           emitpcode(POC_MOVFW,  popGet(AOP(left),0));
6960           emitpcode(POC_MOVWF,  popGet(AOP(result),0));
6961         }
6962
6963         emitpcode(POC_COMFW,  popGet(AOP(right),0));
6964         emitpcode(POC_RRF,    popGet(AOP(result),0));
6965         emitpLabel(tlbl->key);
6966         emitpcode(POC_RLF,    popGet(AOP(result),0));
6967         emitpcode(POC_ADDLW,  popGetLit(1));
6968         emitSKPC;
6969         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6970       }
6971       goto release ;
6972     }
6973     
6974     if (pic14_sameRegs(AOP(left),AOP(result))) {
6975
6976       tlbl = newiTempLabel(NULL);
6977       emitpcode(POC_COMFW,  popGet(AOP(right),0));
6978       genMultiAsm(POC_RRF, result, size,1);
6979       emitpLabel(tlbl->key);
6980       genMultiAsm(POC_RLF, result, size,0);
6981       emitpcode(POC_ADDLW,  popGetLit(1));
6982       emitSKPC;
6983       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
6984       goto release;
6985     }
6986
6987     tlbl = newiTempLabel(NULL);
6988     offset = 0 ;   
6989     tlbl1 = newiTempLabel(NULL);
6990
6991     reAdjustPreg(AOP(result));    
6992     
6993     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
6994     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
6995     l = aopGet(AOP(result),offset,FALSE,FALSE);
6996     MOVA(l);
6997     pic14_emitcode("add","a,acc");         
6998     aopPut(AOP(result),"a",offset++);
6999     while (--size) {
7000         l = aopGet(AOP(result),offset,FALSE,FALSE);
7001         MOVA(l);
7002         pic14_emitcode("rlc","a");         
7003         aopPut(AOP(result),"a",offset++);
7004     }
7005     reAdjustPreg(AOP(result));
7006
7007     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7008     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7009 release:
7010     freeAsmop (right,NULL,ic,TRUE);
7011     freeAsmop(left,NULL,ic,TRUE);
7012     freeAsmop(result,NULL,ic,TRUE);
7013 }
7014
7015 /*-----------------------------------------------------------------*/
7016 /* genrshOne - right shift a one byte quantity by known count      */
7017 /*-----------------------------------------------------------------*/
7018 static void genrshOne (operand *result, operand *left,
7019                        int shCount, int sign)
7020 {
7021     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7022     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7023 }
7024
7025 /*-----------------------------------------------------------------*/
7026 /* genrshTwo - right shift two bytes by known amount != 0          */
7027 /*-----------------------------------------------------------------*/
7028 static void genrshTwo (operand *result,operand *left,
7029                        int shCount, int sign)
7030 {
7031     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7032     /* if shCount >= 8 */
7033     if (shCount >= 8) {
7034         shCount -= 8 ;
7035         if (shCount)
7036             shiftR1Left2Result(left, MSB16, result, LSB,
7037                                shCount, sign);
7038         else 
7039             movLeft2Result(left, MSB16, result, LSB, sign);
7040         if(sign)
7041           addSign(result, MSB16, sign);
7042         else
7043           emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7044
7045     }
7046
7047     /*  1 <= shCount <= 7 */
7048     else
7049         shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7050 }
7051
7052 /*-----------------------------------------------------------------*/
7053 /* shiftRLong - shift right one long from left to result           */
7054 /* offl = LSB or MSB16                                             */
7055 /*-----------------------------------------------------------------*/
7056 static void shiftRLong (operand *left, int offl,
7057                         operand *result, int sign)
7058 {
7059     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7060     if(!sign)
7061         pic14_emitcode("clr","c");
7062     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7063     if(sign)
7064         pic14_emitcode("mov","c,acc.7");
7065     pic14_emitcode("rrc","a");
7066     aopPut(AOP(result),"a",MSB32-offl);
7067     if(offl == MSB16)
7068         /* add sign of "a" */
7069         addSign(result, MSB32, sign);
7070
7071     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7072     pic14_emitcode("rrc","a");
7073     aopPut(AOP(result),"a",MSB24-offl);
7074
7075     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7076     pic14_emitcode("rrc","a");
7077     aopPut(AOP(result),"a",MSB16-offl);
7078
7079     if(offl == LSB){
7080         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7081         pic14_emitcode("rrc","a");
7082         aopPut(AOP(result),"a",LSB);
7083     }
7084 }
7085
7086 /*-----------------------------------------------------------------*/
7087 /* genrshFour - shift four byte by a known amount != 0             */
7088 /*-----------------------------------------------------------------*/
7089 static void genrshFour (operand *result, operand *left,
7090                         int shCount, int sign)
7091 {
7092     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7093     /* if shifting more that 3 bytes */
7094     if(shCount >= 24 ) {
7095         shCount -= 24;
7096         if(shCount)
7097             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7098         else
7099             movLeft2Result(left, MSB32, result, LSB, sign);
7100         addSign(result, MSB16, sign);
7101     }
7102     else if(shCount >= 16){
7103         shCount -= 16;
7104         if(shCount)
7105             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7106         else{
7107             movLeft2Result(left, MSB24, result, LSB, 0);
7108             movLeft2Result(left, MSB32, result, MSB16, sign);
7109         }
7110         addSign(result, MSB24, sign);
7111     }
7112     else if(shCount >= 8){
7113         shCount -= 8;
7114         if(shCount == 1)
7115             shiftRLong(left, MSB16, result, sign);
7116         else if(shCount == 0){
7117             movLeft2Result(left, MSB16, result, LSB, 0);
7118             movLeft2Result(left, MSB24, result, MSB16, 0);
7119             movLeft2Result(left, MSB32, result, MSB24, sign);
7120             addSign(result, MSB32, sign);
7121         }
7122         else{
7123             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7124             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7125             /* the last shift is signed */
7126             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7127             addSign(result, MSB32, sign);
7128         }
7129     }
7130     else{   /* 1 <= shCount <= 7 */
7131         if(shCount <= 2){
7132             shiftRLong(left, LSB, result, sign);
7133             if(shCount == 2)
7134                 shiftRLong(result, LSB, result, sign);
7135         }
7136         else{
7137             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7138             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7139             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7140         }
7141     }
7142 }
7143
7144 /*-----------------------------------------------------------------*/
7145 /* genRightShiftLiteral - right shifting by known count            */
7146 /*-----------------------------------------------------------------*/
7147 static void genRightShiftLiteral (operand *left,
7148                                   operand *right,
7149                                   operand *result,
7150                                   iCode *ic,
7151                                   int sign)
7152 {    
7153     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7154     int size;
7155
7156     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7157     freeAsmop(right,NULL,ic,TRUE);
7158
7159     aopOp(left,ic,FALSE);
7160     aopOp(result,ic,FALSE);
7161
7162 #if VIEW_SIZE
7163     pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7164              AOP_SIZE(left));
7165 #endif
7166
7167     size = pic14_getDataSize(left);
7168     /* test the LEFT size !!! */
7169
7170     /* I suppose that the left size >= result size */
7171     if(shCount == 0){
7172         size = pic14_getDataSize(result);
7173         while(size--)
7174             movLeft2Result(left, size, result, size, 0);
7175     }
7176
7177     else if(shCount >= (size * 8)){
7178         if(sign)
7179             /* get sign in acc.7 */
7180             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
7181         addSign(result, LSB, sign);
7182     } else{
7183         switch (size) {
7184             case 1:
7185                 genrshOne (result,left,shCount,sign);
7186                 break;
7187
7188             case 2:
7189                 genrshTwo (result,left,shCount,sign);
7190                 break;
7191
7192             case 4:
7193                 genrshFour (result,left,shCount,sign);
7194                 break;
7195             default :
7196                 break;
7197         }
7198
7199         freeAsmop(left,NULL,ic,TRUE);
7200         freeAsmop(result,NULL,ic,TRUE);
7201     }
7202 }
7203
7204 /*-----------------------------------------------------------------*/
7205 /* genSignedRightShift - right shift of signed number              */
7206 /*-----------------------------------------------------------------*/
7207 static void genSignedRightShift (iCode *ic)
7208 {
7209     operand *right, *left, *result;
7210     int size, offset;
7211     char *l;
7212     symbol *tlbl, *tlbl1 ;
7213
7214     /* we do it the hard way put the shift count in b
7215     and loop thru preserving the sign */
7216     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7217
7218     right = IC_RIGHT(ic);
7219     left  = IC_LEFT(ic);
7220     result = IC_RESULT(ic);
7221
7222     aopOp(right,ic,FALSE);  
7223
7224
7225     if ( AOP_TYPE(right) == AOP_LIT) {
7226         genRightShiftLiteral (left,right,result,ic,1);
7227         return ;
7228     }
7229         /* shift count is unknown then we have to form 
7230        a loop get the loop count in B : Note: we take
7231        only the lower order byte since shifting
7232        more that 32 bits make no sense anyway, ( the
7233        largest size of an object can be only 32 bits ) */  
7234
7235     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7236     pic14_emitcode("inc","b");
7237     freeAsmop (right,NULL,ic,TRUE);
7238     aopOp(left,ic,FALSE);
7239     aopOp(result,ic,FALSE);
7240
7241     /* now move the left to the result if they are not the
7242     same */
7243     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7244         AOP_SIZE(result) > 1) {
7245
7246         size = AOP_SIZE(result);
7247         offset=0;
7248         while (size--) {
7249             l = aopGet(AOP(left),offset,FALSE,TRUE);
7250             if (*l == '@' && IS_AOP_PREG(result)) {
7251
7252                 pic14_emitcode("mov","a,%s",l);
7253                 aopPut(AOP(result),"a",offset);
7254             } else
7255                 aopPut(AOP(result),l,offset);
7256             offset++;
7257         }
7258     }
7259
7260     /* mov the highest order bit to OVR */    
7261     tlbl = newiTempLabel(NULL);
7262     tlbl1= newiTempLabel(NULL);
7263
7264     size = AOP_SIZE(result);
7265     offset = size - 1;
7266     pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7267     pic14_emitcode("rlc","a");
7268     pic14_emitcode("mov","ov,c");
7269     /* if it is only one byte then */
7270     if (size == 1) {
7271         l = aopGet(AOP(left),0,FALSE,FALSE);
7272         MOVA(l);
7273         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7274         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7275         pic14_emitcode("mov","c,ov");
7276         pic14_emitcode("rrc","a");
7277         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7278         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7279         aopPut(AOP(result),"a",0);
7280         goto release ;
7281     }
7282
7283     reAdjustPreg(AOP(result));
7284     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7285     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7286     pic14_emitcode("mov","c,ov");
7287     while (size--) {
7288         l = aopGet(AOP(result),offset,FALSE,FALSE);
7289         MOVA(l);
7290         pic14_emitcode("rrc","a");         
7291         aopPut(AOP(result),"a",offset--);
7292     }
7293     reAdjustPreg(AOP(result));
7294     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7295     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7296
7297 release:
7298     freeAsmop(left,NULL,ic,TRUE);
7299     freeAsmop(result,NULL,ic,TRUE);
7300 }
7301
7302 /*-----------------------------------------------------------------*/
7303 /* genRightShift - generate code for right shifting                */
7304 /*-----------------------------------------------------------------*/
7305 static void genRightShift (iCode *ic)
7306 {
7307     operand *right, *left, *result;
7308     sym_link *retype ;
7309     int size, offset;
7310     char *l;
7311     symbol *tlbl, *tlbl1 ;
7312
7313     /* if signed then we do it the hard way preserve the
7314     sign bit moving it inwards */
7315     retype = getSpec(operandType(IC_RESULT(ic)));
7316     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7317
7318     if (!SPEC_USIGN(retype)) {
7319         genSignedRightShift (ic);
7320         return ;
7321     }
7322
7323     /* signed & unsigned types are treated the same : i.e. the
7324     signed is NOT propagated inwards : quoting from the
7325     ANSI - standard : "for E1 >> E2, is equivalent to division
7326     by 2**E2 if unsigned or if it has a non-negative value,
7327     otherwise the result is implementation defined ", MY definition
7328     is that the sign does not get propagated */
7329
7330     right = IC_RIGHT(ic);
7331     left  = IC_LEFT(ic);
7332     result = IC_RESULT(ic);
7333
7334     aopOp(right,ic,FALSE);
7335
7336     /* if the shift count is known then do it 
7337     as efficiently as possible */
7338     if (AOP_TYPE(right) == AOP_LIT) {
7339         genRightShiftLiteral (left,right,result,ic, 0);
7340         return ;
7341     }
7342
7343     /* shift count is unknown then we have to form 
7344     a loop get the loop count in B : Note: we take
7345     only the lower order byte since shifting
7346     more that 32 bits make no sense anyway, ( the
7347     largest size of an object can be only 32 bits ) */  
7348
7349     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7350     pic14_emitcode("inc","b");
7351     aopOp(left,ic,FALSE);
7352     aopOp(result,ic,FALSE);
7353
7354     /* now move the left to the result if they are not the
7355     same */
7356     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7357         AOP_SIZE(result) > 1) {
7358
7359         size = AOP_SIZE(result);
7360         offset=0;
7361         while (size--) {
7362             l = aopGet(AOP(left),offset,FALSE,TRUE);
7363             if (*l == '@' && IS_AOP_PREG(result)) {
7364
7365                 pic14_emitcode("mov","a,%s",l);
7366                 aopPut(AOP(result),"a",offset);
7367             } else
7368                 aopPut(AOP(result),l,offset);
7369             offset++;
7370         }
7371     }
7372
7373     tlbl = newiTempLabel(NULL);
7374     tlbl1= newiTempLabel(NULL);
7375     size = AOP_SIZE(result);
7376     offset = size - 1;
7377
7378     /* if it is only one byte then */
7379     if (size == 1) {
7380 /*
7381         l = aopGet(AOP(left),0,FALSE,FALSE);
7382         MOVA(l);
7383         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7384         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7385         CLRC;
7386         pic14_emitcode("rrc","a");
7387         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7388         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7389         aopPut(AOP(result),"a",0);
7390 */
7391         tlbl = newiTempLabel(NULL);
7392         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7393           emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7394           emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7395         }
7396
7397         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7398         emitpcode(POC_RLF,    popGet(AOP(result),0));
7399         emitpLabel(tlbl->key);
7400         emitpcode(POC_RRF,    popGet(AOP(result),0));
7401         emitpcode(POC_ADDLW,  popGetLit(1));
7402         emitSKPC;
7403         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7404
7405         goto release ;
7406     }
7407
7408     reAdjustPreg(AOP(result));
7409     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7410     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7411     CLRC;
7412     while (size--) {
7413         l = aopGet(AOP(result),offset,FALSE,FALSE);
7414         MOVA(l);
7415         pic14_emitcode("rrc","a");         
7416         aopPut(AOP(result),"a",offset--);
7417     }
7418     reAdjustPreg(AOP(result));
7419
7420     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7421     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7422
7423 release:
7424     freeAsmop(left,NULL,ic,TRUE);
7425     freeAsmop (right,NULL,ic,TRUE);
7426     freeAsmop(result,NULL,ic,TRUE);
7427 }
7428
7429 /*-----------------------------------------------------------------*/
7430 /* genUnpackBits - generates code for unpacking bits               */
7431 /*-----------------------------------------------------------------*/
7432 static void genUnpackBits (operand *result, char *rname, int ptype)
7433 {    
7434     int shCnt ;
7435     int rlen = 0 ;
7436     sym_link *etype;
7437     int offset = 0 ;
7438
7439     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7440     etype = getSpec(operandType(result));
7441
7442     /* read the first byte  */
7443     switch (ptype) {
7444
7445     case POINTER:
7446     case IPOINTER:
7447         pic14_emitcode("mov","a,@%s",rname);
7448         break;
7449         
7450     case PPOINTER:
7451         pic14_emitcode("movx","a,@%s",rname);
7452         break;
7453         
7454     case FPOINTER:
7455         pic14_emitcode("movx","a,@dptr");
7456         break;
7457
7458     case CPOINTER:
7459         pic14_emitcode("clr","a");
7460         pic14_emitcode("movc","a","@a+dptr");
7461         break;
7462
7463     case GPOINTER:
7464         pic14_emitcode("lcall","__gptrget");
7465         break;
7466     }
7467
7468     /* if we have bitdisplacement then it fits   */
7469     /* into this byte completely or if length is */
7470     /* less than a byte                          */
7471     if ((shCnt = SPEC_BSTR(etype)) || 
7472         (SPEC_BLEN(etype) <= 8))  {
7473
7474         /* shift right acc */
7475         AccRsh(shCnt);
7476
7477         pic14_emitcode("anl","a,#0x%02x",
7478                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7479         aopPut(AOP(result),"a",offset);
7480         return ;
7481     }
7482
7483     /* bit field did not fit in a byte  */
7484     rlen = SPEC_BLEN(etype) - 8;
7485     aopPut(AOP(result),"a",offset++);
7486
7487     while (1)  {
7488
7489         switch (ptype) {
7490         case POINTER:
7491         case IPOINTER:
7492             pic14_emitcode("inc","%s",rname);
7493             pic14_emitcode("mov","a,@%s",rname);
7494             break;
7495             
7496         case PPOINTER:
7497             pic14_emitcode("inc","%s",rname);
7498             pic14_emitcode("movx","a,@%s",rname);
7499             break;
7500
7501         case FPOINTER:
7502             pic14_emitcode("inc","dptr");
7503             pic14_emitcode("movx","a,@dptr");
7504             break;
7505             
7506         case CPOINTER:
7507             pic14_emitcode("clr","a");
7508             pic14_emitcode("inc","dptr");
7509             pic14_emitcode("movc","a","@a+dptr");
7510             break;
7511             
7512         case GPOINTER:
7513             pic14_emitcode("inc","dptr");
7514             pic14_emitcode("lcall","__gptrget");
7515             break;
7516         }
7517
7518         rlen -= 8;            
7519         /* if we are done */
7520         if ( rlen <= 0 )
7521             break ;
7522         
7523         aopPut(AOP(result),"a",offset++);
7524                               
7525     }
7526     
7527     if (rlen) {
7528         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7529         aopPut(AOP(result),"a",offset);        
7530     }
7531     
7532     return ;
7533 }
7534
7535
7536 /*-----------------------------------------------------------------*/
7537 /* genDataPointerGet - generates code when ptr offset is known     */
7538 /*-----------------------------------------------------------------*/
7539 static void genDataPointerGet (operand *left, 
7540                                operand *result, 
7541                                iCode *ic)
7542 {
7543   int size , offset = 0;
7544
7545
7546   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7547
7548
7549   /* optimization - most of the time, left and result are the same
7550    * address, but different types. for the pic code, we could omit
7551    * the following
7552    */
7553
7554   aopOp(result,ic,TRUE);
7555
7556   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7557
7558   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7559
7560   size = AOP_SIZE(result);
7561
7562   while (size--) {
7563     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7564     offset++;
7565   }
7566
7567   freeAsmop(left,NULL,ic,TRUE);
7568   freeAsmop(result,NULL,ic,TRUE);
7569 }
7570
7571 /*-----------------------------------------------------------------*/
7572 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7573 /*-----------------------------------------------------------------*/
7574 static void genNearPointerGet (operand *left, 
7575                                operand *result, 
7576                                iCode *ic)
7577 {
7578     asmop *aop = NULL;
7579     regs *preg = NULL ;
7580     char *rname ;
7581     sym_link *rtype, *retype;
7582     sym_link *ltype = operandType(left);    
7583     char buffer[80];
7584
7585     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7586
7587     rtype = operandType(result);
7588     retype= getSpec(rtype);
7589     
7590     aopOp(left,ic,FALSE);
7591     
7592     /* if left is rematerialisable and
7593        result is not bit variable type and
7594        the left is pointer to data space i.e
7595        lower 128 bytes of space */
7596     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
7597         !IS_BITVAR(retype)         &&
7598         DCL_TYPE(ltype) == POINTER) {
7599       //genDataPointerGet (left,result,ic);
7600         return ;
7601     }
7602     
7603     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7604
7605         /* if the value is already in a pointer register
7606        then don't need anything more */
7607     if (!AOP_INPREG(AOP(left))) {
7608         /* otherwise get a free pointer register */
7609     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7610         aop = newAsmop(0);
7611         preg = getFreePtr(ic,&aop,FALSE);
7612         pic14_emitcode("mov","%s,%s",
7613                 preg->name,
7614                 aopGet(AOP(left),0,FALSE,TRUE));
7615         rname = preg->name ;
7616     } else
7617         rname = aopGet(AOP(left),0,FALSE,FALSE);
7618     
7619     freeAsmop(left,NULL,ic,TRUE);
7620     aopOp (result,ic,FALSE);
7621     
7622       /* if bitfield then unpack the bits */
7623     if (IS_BITVAR(retype)) 
7624         genUnpackBits (result,rname,POINTER);
7625     else {
7626         /* we have can just get the values */
7627         int size = AOP_SIZE(result);
7628         int offset = 0 ;        
7629         
7630     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7631         while (size--) {
7632             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7633
7634                 pic14_emitcode("mov","a,@%s",rname);
7635                 aopPut(AOP(result),"a",offset);
7636             } else {
7637                 sprintf(buffer,"@%s",rname);
7638                 aopPut(AOP(result),buffer,offset);
7639             }
7640             offset++ ;
7641             if (size)
7642                 pic14_emitcode("inc","%s",rname);
7643         }
7644     }
7645
7646     /* now some housekeeping stuff */
7647     if (aop) {
7648         /* we had to allocate for this iCode */
7649     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7650         freeAsmop(NULL,aop,ic,TRUE);
7651     } else { 
7652         /* we did not allocate which means left
7653            already in a pointer register, then
7654            if size > 0 && this could be used again
7655            we have to point it back to where it 
7656            belongs */
7657     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7658         if (AOP_SIZE(result) > 1 &&
7659             !OP_SYMBOL(left)->remat &&
7660             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7661               ic->depth )) {
7662             int size = AOP_SIZE(result) - 1;
7663             while (size--)
7664                 pic14_emitcode("dec","%s",rname);
7665         }
7666     }
7667
7668     /* done */
7669     freeAsmop(result,NULL,ic,TRUE);
7670      
7671 }
7672
7673 /*-----------------------------------------------------------------*/
7674 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
7675 /*-----------------------------------------------------------------*/
7676 static void genPagedPointerGet (operand *left, 
7677                                operand *result, 
7678                                iCode *ic)
7679 {
7680     asmop *aop = NULL;
7681     regs *preg = NULL ;
7682     char *rname ;
7683     sym_link *rtype, *retype;    
7684
7685     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7686
7687     rtype = operandType(result);
7688     retype= getSpec(rtype);
7689     
7690     aopOp(left,ic,FALSE);
7691
7692   /* if the value is already in a pointer register
7693        then don't need anything more */
7694     if (!AOP_INPREG(AOP(left))) {
7695         /* otherwise get a free pointer register */
7696         aop = newAsmop(0);
7697         preg = getFreePtr(ic,&aop,FALSE);
7698         pic14_emitcode("mov","%s,%s",
7699                 preg->name,
7700                 aopGet(AOP(left),0,FALSE,TRUE));
7701         rname = preg->name ;
7702     } else
7703         rname = aopGet(AOP(left),0,FALSE,FALSE);
7704     
7705     freeAsmop(left,NULL,ic,TRUE);
7706     aopOp (result,ic,FALSE);
7707
7708     /* if bitfield then unpack the bits */
7709     if (IS_BITVAR(retype)) 
7710         genUnpackBits (result,rname,PPOINTER);
7711     else {
7712         /* we have can just get the values */
7713         int size = AOP_SIZE(result);
7714         int offset = 0 ;        
7715         
7716         while (size--) {
7717             
7718             pic14_emitcode("movx","a,@%s",rname);
7719             aopPut(AOP(result),"a",offset);
7720             
7721             offset++ ;
7722             
7723             if (size)
7724                 pic14_emitcode("inc","%s",rname);
7725         }
7726     }
7727
7728     /* now some housekeeping stuff */
7729     if (aop) {
7730         /* we had to allocate for this iCode */
7731         freeAsmop(NULL,aop,ic,TRUE);
7732     } else { 
7733         /* we did not allocate which means left
7734            already in a pointer register, then
7735            if size > 0 && this could be used again
7736            we have to point it back to where it 
7737            belongs */
7738         if (AOP_SIZE(result) > 1 &&
7739             !OP_SYMBOL(left)->remat &&
7740             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7741               ic->depth )) {
7742             int size = AOP_SIZE(result) - 1;
7743             while (size--)
7744                 pic14_emitcode("dec","%s",rname);
7745         }
7746     }
7747
7748     /* done */
7749     freeAsmop(result,NULL,ic,TRUE);
7750     
7751         
7752 }
7753
7754 /*-----------------------------------------------------------------*/
7755 /* genFarPointerGet - gget value from far space                    */
7756 /*-----------------------------------------------------------------*/
7757 static void genFarPointerGet (operand *left,
7758                               operand *result, iCode *ic)
7759 {
7760     int size, offset ;
7761     sym_link *retype = getSpec(operandType(result));
7762
7763     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7764
7765     aopOp(left,ic,FALSE);
7766
7767     /* if the operand is already in dptr 
7768     then we do nothing else we move the value to dptr */
7769     if (AOP_TYPE(left) != AOP_STR) {
7770         /* if this is remateriazable */
7771         if (AOP_TYPE(left) == AOP_IMMD)
7772             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7773         else { /* we need to get it byte by byte */
7774             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7775             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7776             if (options.model == MODEL_FLAT24)
7777             {
7778                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7779             }
7780         }
7781     }
7782     /* so dptr know contains the address */
7783     freeAsmop(left,NULL,ic,TRUE);
7784     aopOp(result,ic,FALSE);
7785
7786     /* if bit then unpack */
7787     if (IS_BITVAR(retype)) 
7788         genUnpackBits(result,"dptr",FPOINTER);
7789     else {
7790         size = AOP_SIZE(result);
7791         offset = 0 ;
7792
7793         while (size--) {
7794             pic14_emitcode("movx","a,@dptr");
7795             aopPut(AOP(result),"a",offset++);
7796             if (size)
7797                 pic14_emitcode("inc","dptr");
7798         }
7799     }
7800
7801     freeAsmop(result,NULL,ic,TRUE);
7802 }
7803 #if 0
7804 /*-----------------------------------------------------------------*/
7805 /* genCodePointerGet - get value from code space                  */
7806 /*-----------------------------------------------------------------*/
7807 static void genCodePointerGet (operand *left,
7808                                 operand *result, iCode *ic)
7809 {
7810     int size, offset ;
7811     sym_link *retype = getSpec(operandType(result));
7812
7813     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7814
7815     aopOp(left,ic,FALSE);
7816
7817     /* if the operand is already in dptr 
7818     then we do nothing else we move the value to dptr */
7819     if (AOP_TYPE(left) != AOP_STR) {
7820         /* if this is remateriazable */
7821         if (AOP_TYPE(left) == AOP_IMMD)
7822             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7823         else { /* we need to get it byte by byte */
7824             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7825             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7826             if (options.model == MODEL_FLAT24)
7827             {
7828                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7829             }
7830         }
7831     }
7832     /* so dptr know contains the address */
7833     freeAsmop(left,NULL,ic,TRUE);
7834     aopOp(result,ic,FALSE);
7835
7836     /* if bit then unpack */
7837     if (IS_BITVAR(retype)) 
7838         genUnpackBits(result,"dptr",CPOINTER);
7839     else {
7840         size = AOP_SIZE(result);
7841         offset = 0 ;
7842
7843         while (size--) {
7844             pic14_emitcode("clr","a");
7845             pic14_emitcode("movc","a,@a+dptr");
7846             aopPut(AOP(result),"a",offset++);
7847             if (size)
7848                 pic14_emitcode("inc","dptr");
7849         }
7850     }
7851
7852     freeAsmop(result,NULL,ic,TRUE);
7853 }
7854 #endif
7855 /*-----------------------------------------------------------------*/
7856 /* genGenPointerGet - gget value from generic pointer space        */
7857 /*-----------------------------------------------------------------*/
7858 static void genGenPointerGet (operand *left,
7859                               operand *result, iCode *ic)
7860 {
7861   int size, offset ;
7862   sym_link *retype = getSpec(operandType(result));
7863
7864   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7865   aopOp(left,ic,FALSE);
7866   aopOp(result,ic,FALSE);
7867
7868
7869   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7870
7871   /* if the operand is already in dptr 
7872      then we do nothing else we move the value to dptr */
7873   //  if (AOP_TYPE(left) != AOP_STR) {
7874     /* if this is remateriazable */
7875     if (AOP_TYPE(left) == AOP_IMMD) {
7876       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7877       pic14_emitcode("mov","b,#%d",pointerCode(retype));
7878     }
7879     else { /* we need to get it byte by byte */
7880
7881       emitpcode(POC_MOVFW,popGet(AOP(left),0));
7882       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7883
7884       size = AOP_SIZE(result);
7885       offset = 0 ;
7886
7887       while(size--) {
7888         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7889         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7890         if(size)
7891           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7892       }
7893       goto release;
7894     }
7895     //}
7896   /* so dptr know contains the address */
7897
7898   /* if bit then unpack */
7899   //if (IS_BITVAR(retype)) 
7900   //  genUnpackBits(result,"dptr",GPOINTER);
7901
7902  release:
7903   freeAsmop(left,NULL,ic,TRUE);
7904   freeAsmop(result,NULL,ic,TRUE);
7905
7906 }
7907
7908 /*-----------------------------------------------------------------*/
7909 /* genConstPointerGet - get value from const generic pointer space */
7910 /*-----------------------------------------------------------------*/
7911 static void genConstPointerGet (operand *left,
7912                                 operand *result, iCode *ic)
7913 {
7914   //sym_link *retype = getSpec(operandType(result));
7915   symbol *albl = newiTempLabel(NULL);
7916   symbol *blbl = newiTempLabel(NULL);
7917   PIC_OPCODE poc;
7918
7919   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7920   aopOp(left,ic,FALSE);
7921   aopOp(result,ic,FALSE);
7922
7923
7924   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7925
7926   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
7927
7928   emitpcode(POC_CALL,popGetLabel(albl->key));
7929   emitpcode(POC_GOTO,popGetLabel(blbl->key));
7930   emitpLabel(albl->key);
7931
7932   poc = ( (AOP_TYPE(left) == AOP_IMMD) ? POC_MOVLW : POC_MOVFW);
7933     
7934   emitpcode(poc,popGet(AOP(left),1));
7935   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
7936   emitpcode(poc,popGet(AOP(left),0));
7937   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
7938
7939   emitpLabel(blbl->key);
7940
7941   emitpcode(POC_MOVWF,popGet(AOP(result),0));
7942
7943
7944   freeAsmop(left,NULL,ic,TRUE);
7945   freeAsmop(result,NULL,ic,TRUE);
7946
7947 }
7948 /*-----------------------------------------------------------------*/
7949 /* genPointerGet - generate code for pointer get                   */
7950 /*-----------------------------------------------------------------*/
7951 static void genPointerGet (iCode *ic)
7952 {
7953     operand *left, *result ;
7954     sym_link *type, *etype;
7955     int p_type;
7956
7957     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7958
7959     left = IC_LEFT(ic);
7960     result = IC_RESULT(ic) ;
7961
7962     /* depending on the type of pointer we need to
7963     move it to the correct pointer register */
7964     type = operandType(left);
7965     etype = getSpec(type);
7966
7967     if (IS_PTR_CONST(type))
7968       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
7969
7970     /* if left is of type of pointer then it is simple */
7971     if (IS_PTR(type) && !IS_FUNC(type->next)) 
7972         p_type = DCL_TYPE(type);
7973     else {
7974         /* we have to go by the storage class */
7975         p_type = PTR_TYPE(SPEC_OCLS(etype));
7976
7977         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
7978
7979         if (SPEC_OCLS(etype)->codesp ) {
7980           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
7981           //p_type = CPOINTER ; 
7982         }
7983         else
7984             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
7985               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
7986                /*p_type = FPOINTER ;*/ 
7987             else
7988                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
7989                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
7990 /*                  p_type = PPOINTER; */
7991                 else
7992                     if (SPEC_OCLS(etype) == idata )
7993                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
7994 /*                      p_type = IPOINTER; */
7995                     else
7996                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
7997 /*                      p_type = POINTER ; */
7998     }
7999
8000     /* now that we have the pointer type we assign
8001     the pointer values */
8002     switch (p_type) {
8003
8004     case POINTER:       
8005     case IPOINTER:
8006         genNearPointerGet (left,result,ic);
8007         break;
8008
8009     case PPOINTER:
8010         genPagedPointerGet(left,result,ic);
8011         break;
8012
8013     case FPOINTER:
8014         genFarPointerGet (left,result,ic);
8015         break;
8016
8017     case CPOINTER:
8018         genConstPointerGet (left,result,ic);
8019         //pic14_emitcodePointerGet (left,result,ic);
8020         break;
8021
8022     case GPOINTER:
8023       if (IS_PTR_CONST(type))
8024         genConstPointerGet (left,result,ic);
8025       else
8026         genGenPointerGet (left,result,ic);
8027       break;
8028     }
8029
8030 }
8031
8032 /*-----------------------------------------------------------------*/
8033 /* genPackBits - generates code for packed bit storage             */
8034 /*-----------------------------------------------------------------*/
8035 static void genPackBits (sym_link    *etype ,
8036                          operand *right ,
8037                          char *rname, int p_type)
8038 {
8039     int shCount = 0 ;
8040     int offset = 0  ;
8041     int rLen = 0 ;
8042     int blen, bstr ;   
8043     char *l ;
8044
8045     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8046     blen = SPEC_BLEN(etype);
8047     bstr = SPEC_BSTR(etype);
8048
8049     l = aopGet(AOP(right),offset++,FALSE,FALSE);
8050     MOVA(l);   
8051
8052     /* if the bit lenth is less than or    */
8053     /* it exactly fits a byte then         */
8054     if (SPEC_BLEN(etype) <= 8 )  {
8055         shCount = SPEC_BSTR(etype) ;
8056
8057         /* shift left acc */
8058         AccLsh(shCount);
8059
8060         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8061
8062
8063             switch (p_type) {
8064                 case POINTER:
8065                     pic14_emitcode ("mov","b,a");
8066                     pic14_emitcode("mov","a,@%s",rname);
8067                     break;
8068
8069                 case FPOINTER:
8070                     pic14_emitcode ("mov","b,a");
8071                     pic14_emitcode("movx","a,@dptr");
8072                     break;
8073
8074                 case GPOINTER:
8075                     pic14_emitcode ("push","b");
8076                     pic14_emitcode ("push","acc");
8077                     pic14_emitcode ("lcall","__gptrget");
8078                     pic14_emitcode ("pop","b");
8079                     break;
8080             }
8081
8082             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8083                       ((unsigned char)(0xFF << (blen+bstr)) | 
8084                        (unsigned char)(0xFF >> (8-bstr)) ) );
8085             pic14_emitcode ("orl","a,b");
8086             if (p_type == GPOINTER)
8087                 pic14_emitcode("pop","b");
8088         }
8089     }
8090
8091     switch (p_type) {
8092         case POINTER:
8093             pic14_emitcode("mov","@%s,a",rname);
8094             break;
8095
8096         case FPOINTER:
8097             pic14_emitcode("movx","@dptr,a");
8098             break;
8099
8100         case GPOINTER:
8101             DEBUGpic14_emitcode(";lcall","__gptrput");
8102             break;
8103     }
8104
8105     /* if we r done */
8106     if ( SPEC_BLEN(etype) <= 8 )
8107         return ;
8108
8109     pic14_emitcode("inc","%s",rname);
8110     rLen = SPEC_BLEN(etype) ;     
8111
8112     /* now generate for lengths greater than one byte */
8113     while (1) {
8114
8115         l = aopGet(AOP(right),offset++,FALSE,TRUE);
8116
8117         rLen -= 8 ;
8118         if (rLen <= 0 )
8119             break ;
8120
8121         switch (p_type) {
8122             case POINTER:
8123                 if (*l == '@') {
8124                     MOVA(l);
8125                     pic14_emitcode("mov","@%s,a",rname);
8126                 } else
8127                     pic14_emitcode("mov","@%s,%s",rname,l);
8128                 break;
8129
8130             case FPOINTER:
8131                 MOVA(l);
8132                 pic14_emitcode("movx","@dptr,a");
8133                 break;
8134
8135             case GPOINTER:
8136                 MOVA(l);
8137                 DEBUGpic14_emitcode(";lcall","__gptrput");
8138                 break;  
8139         }   
8140         pic14_emitcode ("inc","%s",rname);
8141     }
8142
8143     MOVA(l);
8144
8145     /* last last was not complete */
8146     if (rLen)   {
8147         /* save the byte & read byte */
8148         switch (p_type) {
8149             case POINTER:
8150                 pic14_emitcode ("mov","b,a");
8151                 pic14_emitcode("mov","a,@%s",rname);
8152                 break;
8153
8154             case FPOINTER:
8155                 pic14_emitcode ("mov","b,a");
8156                 pic14_emitcode("movx","a,@dptr");
8157                 break;
8158
8159             case GPOINTER:
8160                 pic14_emitcode ("push","b");
8161                 pic14_emitcode ("push","acc");
8162                 pic14_emitcode ("lcall","__gptrget");
8163                 pic14_emitcode ("pop","b");
8164                 break;
8165         }
8166
8167         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8168         pic14_emitcode ("orl","a,b");
8169     }
8170
8171     if (p_type == GPOINTER)
8172         pic14_emitcode("pop","b");
8173
8174     switch (p_type) {
8175
8176     case POINTER:
8177         pic14_emitcode("mov","@%s,a",rname);
8178         break;
8179         
8180     case FPOINTER:
8181         pic14_emitcode("movx","@dptr,a");
8182         break;
8183         
8184     case GPOINTER:
8185         DEBUGpic14_emitcode(";lcall","__gptrput");
8186         break;                  
8187     }
8188 }
8189 /*-----------------------------------------------------------------*/
8190 /* genDataPointerSet - remat pointer to data space                 */
8191 /*-----------------------------------------------------------------*/
8192 static void genDataPointerSet(operand *right,
8193                               operand *result,
8194                               iCode *ic)
8195 {
8196     int size, offset = 0 ;
8197     char *l, buffer[256];
8198
8199     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8200     aopOp(right,ic,FALSE);
8201     
8202     l = aopGet(AOP(result),0,FALSE,TRUE);
8203     size = AOP_SIZE(right);
8204     if ( AOP_TYPE(result) == AOP_PCODE) {
8205       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8206               AOP(result)->aopu.pcop->name,
8207               PCOI(AOP(result)->aopu.pcop)->offset);
8208     }
8209
8210     // tsd, was l+1 - the underline `_' prefix was being stripped
8211     while (size--) {
8212       if (offset) {
8213         sprintf(buffer,"(%s + %d)",l,offset);
8214         fprintf(stderr,"oops  %s\n",buffer);
8215       } else
8216         sprintf(buffer,"%s",l);
8217
8218         if (AOP_TYPE(right) == AOP_LIT) {
8219           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8220           lit = lit >> (8*offset);
8221           if(lit&0xff) {
8222             pic14_emitcode("movlw","%d",lit);
8223             pic14_emitcode("movwf","%s",buffer);
8224
8225             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8226             //emitpcode(POC_MOVWF, popRegFromString(buffer));
8227             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8228
8229           } else {
8230             pic14_emitcode("clrf","%s",buffer);
8231             //emitpcode(POC_CLRF, popRegFromString(buffer));
8232             emitpcode(POC_CLRF, popGet(AOP(result),0));
8233           }
8234         }else {
8235           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8236           pic14_emitcode("movwf","%s",buffer);
8237
8238           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8239           //emitpcode(POC_MOVWF, popRegFromString(buffer));
8240           emitpcode(POC_MOVWF, popGet(AOP(result),0));
8241
8242         }
8243
8244         offset++;
8245     }
8246
8247     freeAsmop(right,NULL,ic,TRUE);
8248     freeAsmop(result,NULL,ic,TRUE);
8249 }
8250
8251 /*-----------------------------------------------------------------*/
8252 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8253 /*-----------------------------------------------------------------*/
8254 static void genNearPointerSet (operand *right,
8255                                operand *result, 
8256                                iCode *ic)
8257 {
8258     asmop *aop = NULL;
8259     char *l;
8260     sym_link *retype;
8261     sym_link *ptype = operandType(result);
8262
8263     
8264     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8265     retype= getSpec(operandType(right));
8266
8267     aopOp(result,ic,FALSE);
8268     
8269     /* if the result is rematerializable &
8270        in data space & not a bit variable */
8271     //if (AOP_TYPE(result) == AOP_IMMD &&
8272     if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8273         DCL_TYPE(ptype) == POINTER   &&
8274         !IS_BITVAR(retype)) {
8275         genDataPointerSet (right,result,ic);
8276         return;
8277     }
8278
8279     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8280
8281     /* if the value is already in a pointer register
8282     then don't need anything more */
8283     if (!AOP_INPREG(AOP(result))) {
8284         /* otherwise get a free pointer register */
8285         //aop = newAsmop(0);
8286         //preg = getFreePtr(ic,&aop,FALSE);
8287         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8288         //pic14_emitcode("mov","%s,%s",
8289         //         preg->name,
8290         //         aopGet(AOP(result),0,FALSE,TRUE));
8291         //rname = preg->name ;
8292         pic14_emitcode("movwf","fsr");
8293     }// else
8294     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8295
8296     freeAsmop(result,NULL,ic,TRUE);
8297     aopOp (right,ic,FALSE);
8298     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8299
8300     /* if bitfield then unpack the bits */
8301     if (IS_BITVAR(retype)) {
8302       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8303              "The programmer is obviously confused");
8304       //genPackBits (retype,right,rname,POINTER);
8305       exit(1);
8306     }
8307     else {
8308         /* we have can just get the values */
8309         int size = AOP_SIZE(right);
8310         int offset = 0 ;    
8311
8312     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8313         while (size--) {
8314             l = aopGet(AOP(right),offset,FALSE,TRUE);
8315             if (*l == '@' ) {
8316               //MOVA(l);
8317               //pic14_emitcode("mov","@%s,a",rname);
8318               pic14_emitcode("movf","indf,w ;1");
8319             } else {
8320
8321               if (AOP_TYPE(right) == AOP_LIT) {
8322                 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8323                 if(lit) {
8324                   pic14_emitcode("movlw","%s",l);
8325                   pic14_emitcode("movwf","indf ;2");
8326                 } else 
8327                   pic14_emitcode("clrf","indf");
8328               }else {
8329                 pic14_emitcode("movf","%s,w",l);
8330                 pic14_emitcode("movwf","indf ;2");
8331               }
8332             //pic14_emitcode("mov","@%s,%s",rname,l);
8333             }
8334             if (size)
8335               pic14_emitcode("incf","fsr,f ;3");
8336             //pic14_emitcode("inc","%s",rname);
8337             offset++;
8338         }
8339     }
8340
8341     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8342     /* now some housekeeping stuff */
8343     if (aop) {
8344         /* we had to allocate for this iCode */
8345         freeAsmop(NULL,aop,ic,TRUE);
8346     } else { 
8347         /* we did not allocate which means left
8348         already in a pointer register, then
8349         if size > 0 && this could be used again
8350         we have to point it back to where it 
8351         belongs */
8352     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8353         if (AOP_SIZE(right) > 1 &&
8354             !OP_SYMBOL(result)->remat &&
8355             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8356               ic->depth )) {
8357             int size = AOP_SIZE(right) - 1;
8358             while (size--)
8359               pic14_emitcode("decf","fsr,f");
8360               //pic14_emitcode("dec","%s",rname);
8361         }
8362     }
8363
8364     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8365     /* done */
8366     freeAsmop(right,NULL,ic,TRUE);
8367
8368
8369 }
8370
8371 /*-----------------------------------------------------------------*/
8372 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8373 /*-----------------------------------------------------------------*/
8374 static void genPagedPointerSet (operand *right,
8375                                operand *result, 
8376                                iCode *ic)
8377 {
8378     asmop *aop = NULL;
8379     regs *preg = NULL ;
8380     char *rname , *l;
8381     sym_link *retype;
8382        
8383     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8384
8385     retype= getSpec(operandType(right));
8386     
8387     aopOp(result,ic,FALSE);
8388     
8389     /* if the value is already in a pointer register
8390        then don't need anything more */
8391     if (!AOP_INPREG(AOP(result))) {
8392         /* otherwise get a free pointer register */
8393         aop = newAsmop(0);
8394         preg = getFreePtr(ic,&aop,FALSE);
8395         pic14_emitcode("mov","%s,%s",
8396                 preg->name,
8397                 aopGet(AOP(result),0,FALSE,TRUE));
8398         rname = preg->name ;
8399     } else
8400         rname = aopGet(AOP(result),0,FALSE,FALSE);
8401     
8402     freeAsmop(result,NULL,ic,TRUE);
8403     aopOp (right,ic,FALSE);
8404
8405     /* if bitfield then unpack the bits */
8406     if (IS_BITVAR(retype)) 
8407         genPackBits (retype,right,rname,PPOINTER);
8408     else {
8409         /* we have can just get the values */
8410         int size = AOP_SIZE(right);
8411         int offset = 0 ;        
8412         
8413         while (size--) {
8414             l = aopGet(AOP(right),offset,FALSE,TRUE);
8415             
8416             MOVA(l);
8417             pic14_emitcode("movx","@%s,a",rname);
8418
8419             if (size)
8420                 pic14_emitcode("inc","%s",rname);
8421
8422             offset++;
8423         }
8424     }
8425     
8426     /* now some housekeeping stuff */
8427     if (aop) {
8428         /* we had to allocate for this iCode */
8429         freeAsmop(NULL,aop,ic,TRUE);
8430     } else { 
8431         /* we did not allocate which means left
8432            already in a pointer register, then
8433            if size > 0 && this could be used again
8434            we have to point it back to where it 
8435            belongs */
8436         if (AOP_SIZE(right) > 1 &&
8437             !OP_SYMBOL(result)->remat &&
8438             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8439               ic->depth )) {
8440             int size = AOP_SIZE(right) - 1;
8441             while (size--)
8442                 pic14_emitcode("dec","%s",rname);
8443         }
8444     }
8445
8446     /* done */
8447     freeAsmop(right,NULL,ic,TRUE);
8448     
8449         
8450 }
8451
8452 /*-----------------------------------------------------------------*/
8453 /* genFarPointerSet - set value from far space                     */
8454 /*-----------------------------------------------------------------*/
8455 static void genFarPointerSet (operand *right,
8456                               operand *result, iCode *ic)
8457 {
8458     int size, offset ;
8459     sym_link *retype = getSpec(operandType(right));
8460
8461     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8462     aopOp(result,ic,FALSE);
8463
8464     /* if the operand is already in dptr 
8465     then we do nothing else we move the value to dptr */
8466     if (AOP_TYPE(result) != AOP_STR) {
8467         /* if this is remateriazable */
8468         if (AOP_TYPE(result) == AOP_IMMD)
8469             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8470         else { /* we need to get it byte by byte */
8471             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8472             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8473             if (options.model == MODEL_FLAT24)
8474             {
8475                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8476             }
8477         }
8478     }
8479     /* so dptr know contains the address */
8480     freeAsmop(result,NULL,ic,TRUE);
8481     aopOp(right,ic,FALSE);
8482
8483     /* if bit then unpack */
8484     if (IS_BITVAR(retype)) 
8485         genPackBits(retype,right,"dptr",FPOINTER);
8486     else {
8487         size = AOP_SIZE(right);
8488         offset = 0 ;
8489
8490         while (size--) {
8491             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8492             MOVA(l);
8493             pic14_emitcode("movx","@dptr,a");
8494             if (size)
8495                 pic14_emitcode("inc","dptr");
8496         }
8497     }
8498
8499     freeAsmop(right,NULL,ic,TRUE);
8500 }
8501
8502 /*-----------------------------------------------------------------*/
8503 /* genGenPointerSet - set value from generic pointer space         */
8504 /*-----------------------------------------------------------------*/
8505 static void genGenPointerSet (operand *right,
8506                               operand *result, iCode *ic)
8507 {
8508   int size, offset ;
8509   sym_link *retype = getSpec(operandType(right));
8510
8511   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8512
8513   aopOp(result,ic,FALSE);
8514   aopOp(right,ic,FALSE);
8515   size = AOP_SIZE(right);
8516
8517   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8518
8519   /* if the operand is already in dptr 
8520      then we do nothing else we move the value to dptr */
8521   if (AOP_TYPE(result) != AOP_STR) {
8522     /* if this is remateriazable */
8523     if (AOP_TYPE(result) == AOP_IMMD) {
8524       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8525       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8526     }
8527     else { /* we need to get it byte by byte */
8528       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8529       size = AOP_SIZE(right);
8530       offset = 0 ;
8531
8532       /* hack hack! see if this the FSR. If so don't load W */
8533       if(AOP_TYPE(right) != AOP_ACC) {
8534
8535         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8536         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8537
8538         //if(size==2)
8539         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8540         //if(size==4) {
8541         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8542         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8543         //}
8544
8545         while(size--) {
8546           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8547           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8548           
8549           if(size)
8550             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8551         }
8552
8553
8554         goto release;
8555       } 
8556
8557       if(aopIdx(AOP(result),0) != 4) {
8558
8559         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8560         goto release;
8561       }
8562
8563       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8564       goto release;
8565
8566     }
8567   }
8568   /* so dptr know contains the address */
8569
8570
8571   /* if bit then unpack */
8572   if (IS_BITVAR(retype)) 
8573     genPackBits(retype,right,"dptr",GPOINTER);
8574   else {
8575     size = AOP_SIZE(right);
8576     offset = 0 ;
8577
8578     while (--size) {
8579       //char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8580       if(size)
8581         pic14_emitcode("incf","fsr,f");
8582       pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8583       pic14_emitcode("movwf","indf");
8584       //MOVA(l);
8585       //DEBUGpic14_emitcode(";lcall","__gptrput");
8586       //if (size)
8587       //    pic14_emitcode("inc","dptr");
8588     }
8589   }
8590
8591  release:
8592   freeAsmop(right,NULL,ic,TRUE);
8593   freeAsmop(result,NULL,ic,TRUE);
8594 }
8595
8596 /*-----------------------------------------------------------------*/
8597 /* genPointerSet - stores the value into a pointer location        */
8598 /*-----------------------------------------------------------------*/
8599 static void genPointerSet (iCode *ic)
8600 {    
8601     operand *right, *result ;
8602     sym_link *type, *etype;
8603     int p_type;
8604
8605     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8606
8607     right = IC_RIGHT(ic);
8608     result = IC_RESULT(ic) ;
8609
8610     /* depending on the type of pointer we need to
8611     move it to the correct pointer register */
8612     type = operandType(result);
8613     etype = getSpec(type);
8614     /* if left is of type of pointer then it is simple */
8615     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8616         p_type = DCL_TYPE(type);
8617     }
8618     else {
8619         /* we have to go by the storage class */
8620         p_type = PTR_TYPE(SPEC_OCLS(etype));
8621
8622 /*      if (SPEC_OCLS(etype)->codesp ) { */
8623 /*          p_type = CPOINTER ;  */
8624 /*      } */
8625 /*      else */
8626 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8627 /*              p_type = FPOINTER ; */
8628 /*          else */
8629 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8630 /*                  p_type = PPOINTER ; */
8631 /*              else */
8632 /*                  if (SPEC_OCLS(etype) == idata ) */
8633 /*                      p_type = IPOINTER ; */
8634 /*                  else */
8635 /*                      p_type = POINTER ; */
8636     }
8637
8638     /* now that we have the pointer type we assign
8639     the pointer values */
8640     switch (p_type) {
8641
8642     case POINTER:
8643     case IPOINTER:
8644         genNearPointerSet (right,result,ic);
8645         break;
8646
8647     case PPOINTER:
8648         genPagedPointerSet (right,result,ic);
8649         break;
8650
8651     case FPOINTER:
8652         genFarPointerSet (right,result,ic);
8653         break;
8654
8655     case GPOINTER:
8656         genGenPointerSet (right,result,ic);
8657         break;
8658
8659     default:
8660       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
8661               "genPointerSet: illegal pointer type");
8662     }
8663 }
8664
8665 /*-----------------------------------------------------------------*/
8666 /* genIfx - generate code for Ifx statement                        */
8667 /*-----------------------------------------------------------------*/
8668 static void genIfx (iCode *ic, iCode *popIc)
8669 {
8670   operand *cond = IC_COND(ic);
8671   int isbit =0;
8672
8673   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8674
8675   aopOp(cond,ic,FALSE);
8676
8677   /* get the value into acc */
8678   if (AOP_TYPE(cond) != AOP_CRY)
8679     pic14_toBoolean(cond);
8680   else
8681     isbit = 1;
8682   /* the result is now in the accumulator */
8683   freeAsmop(cond,NULL,ic,TRUE);
8684
8685   /* if there was something to be popped then do it */
8686   if (popIc)
8687     genIpop(popIc);
8688
8689   /* if the condition is  a bit variable */
8690   if (isbit && IS_ITEMP(cond) && 
8691       SPIL_LOC(cond)) {
8692     genIfxJump(ic,SPIL_LOC(cond)->rname);
8693     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8694   }
8695   else {
8696     if (isbit && !IS_ITEMP(cond))
8697       genIfxJump(ic,OP_SYMBOL(cond)->rname);
8698     else
8699       genIfxJump(ic,"a");
8700   }
8701   ic->generated = 1;
8702
8703 }
8704
8705 /*-----------------------------------------------------------------*/
8706 /* genAddrOf - generates code for address of                       */
8707 /*-----------------------------------------------------------------*/
8708 static void genAddrOf (iCode *ic)
8709 {
8710   //symbol *sym = OP_SYMBOL(IC_LEFT(ic));
8711   operand *right, *result, *left;
8712   //int size, offset ;
8713
8714   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8715
8716
8717   //aopOp(IC_RESULT(ic),ic,FALSE);
8718
8719   aopOp((left=IC_LEFT(ic)),ic,FALSE);
8720   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8721   aopOp((result=IC_RESULT(ic)),ic,TRUE);
8722
8723   DEBUGpic14_AopType(__LINE__,left,right,result);
8724
8725   emitpcode(POC_MOVLW, popGet(AOP(left),0));
8726   emitpcode(POC_MOVWF, popGet(AOP(result),0));
8727
8728 #if 0
8729   /* object not on stack then we need the name */
8730   size = AOP_SIZE(IC_RESULT(ic));
8731   offset = 0;
8732
8733   while (size--) {
8734     char s[SDCC_NAME_MAX];
8735     if (offset) 
8736       sprintf(s,"#(%s >> %d)",
8737               sym->rname,
8738               offset*8);
8739     else
8740       sprintf(s,"#%s",sym->rname);
8741     aopPut(AOP(IC_RESULT(ic)),s,offset++);
8742   }
8743 #endif
8744
8745
8746   //  freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
8747   freeAsmop(left,NULL,ic,FALSE);
8748   freeAsmop(result,NULL,ic,TRUE);
8749
8750 }
8751
8752 #if 0
8753 /*-----------------------------------------------------------------*/
8754 /* genFarFarAssign - assignment when both are in far space         */
8755 /*-----------------------------------------------------------------*/
8756 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8757 {
8758     int size = AOP_SIZE(right);
8759     int offset = 0;
8760     char *l ;
8761     /* first push the right side on to the stack */
8762     while (size--) {
8763         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8764         MOVA(l);
8765         pic14_emitcode ("push","acc");
8766     }
8767     
8768     freeAsmop(right,NULL,ic,FALSE);
8769     /* now assign DPTR to result */
8770     aopOp(result,ic,FALSE);
8771     size = AOP_SIZE(result);
8772     while (size--) {
8773         pic14_emitcode ("pop","acc");
8774         aopPut(AOP(result),"a",--offset);
8775     }
8776     freeAsmop(result,NULL,ic,FALSE);
8777         
8778 }
8779 #endif
8780
8781 /*-----------------------------------------------------------------*/
8782 /* genAssign - generate code for assignment                        */
8783 /*-----------------------------------------------------------------*/
8784 static void genAssign (iCode *ic)
8785 {
8786   operand *result, *right;
8787   int size, offset,know_W;
8788   unsigned long lit = 0L;
8789
8790   result = IC_RESULT(ic);
8791   right  = IC_RIGHT(ic) ;
8792
8793   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8794
8795   /* if they are the same */
8796   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8797     return ;
8798
8799   aopOp(right,ic,FALSE);
8800   aopOp(result,ic,TRUE);
8801
8802   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8803
8804   /* if they are the same registers */
8805   if (pic14_sameRegs(AOP(right),AOP(result)))
8806     goto release;
8807
8808   /* if the result is a bit */
8809   if (AOP_TYPE(result) == AOP_CRY) {
8810
8811     /* if the right size is a literal then
8812        we know what the value is */
8813     if (AOP_TYPE(right) == AOP_LIT) {
8814           
8815       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8816                   popGet(AOP(result),0));
8817
8818       if (((int) operandLitValue(right))) 
8819         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8820                        AOP(result)->aopu.aop_dir,
8821                        AOP(result)->aopu.aop_dir);
8822       else
8823         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8824                        AOP(result)->aopu.aop_dir,
8825                        AOP(result)->aopu.aop_dir);
8826       goto release;
8827     }
8828
8829     /* the right is also a bit variable */
8830     if (AOP_TYPE(right) == AOP_CRY) {
8831       emitpcode(POC_BCF,    popGet(AOP(result),0));
8832       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8833       emitpcode(POC_BSF,    popGet(AOP(result),0));
8834
8835       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8836                      AOP(result)->aopu.aop_dir,
8837                      AOP(result)->aopu.aop_dir);
8838       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8839                      AOP(right)->aopu.aop_dir,
8840                      AOP(right)->aopu.aop_dir);
8841       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8842                      AOP(result)->aopu.aop_dir,
8843                      AOP(result)->aopu.aop_dir);
8844       goto release ;
8845     }
8846
8847     /* we need to or */
8848     emitpcode(POC_BCF,    popGet(AOP(result),0));
8849     pic14_toBoolean(right);
8850     emitSKPZ;
8851     emitpcode(POC_BSF,    popGet(AOP(result),0));
8852     //aopPut(AOP(result),"a",0);
8853     goto release ;
8854   }
8855
8856   /* bit variables done */
8857   /* general case */
8858   size = AOP_SIZE(result);
8859   offset = 0 ;
8860   if(AOP_TYPE(right) == AOP_LIT)
8861     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8862
8863   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
8864   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8865     if(aopIdx(AOP(result),0) == 4) {
8866   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8867       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8868       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8869       goto release;
8870     } else
8871       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
8872   }
8873
8874   know_W=-1;
8875   while (size--) {
8876   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8877     if(AOP_TYPE(right) == AOP_LIT) {
8878       if(lit&0xff) {
8879         if(know_W != (lit&0xff))
8880           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8881         know_W = lit&0xff;
8882         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8883       } else
8884         emitpcode(POC_CLRF, popGet(AOP(result),offset));
8885
8886       lit >>= 8;
8887
8888     } else if (AOP_TYPE(right) == AOP_CRY) {
8889       emitpcode(POC_CLRF, popGet(AOP(result),offset));
8890       if(offset == 0) {
8891         emitpcode(POC_BTFSS, popGet(AOP(right),0));
8892         emitpcode(POC_INCF, popGet(AOP(result),0));
8893       }
8894     } else {
8895   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8896       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8897       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8898     }
8899             
8900     offset++;
8901   }
8902
8903     
8904  release:
8905   freeAsmop (right,NULL,ic,FALSE);
8906   freeAsmop (result,NULL,ic,TRUE);
8907 }   
8908
8909 /*-----------------------------------------------------------------*/
8910 /* genJumpTab - genrates code for jump table                       */
8911 /*-----------------------------------------------------------------*/
8912 static void genJumpTab (iCode *ic)
8913 {
8914     symbol *jtab;
8915     char *l;
8916
8917     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8918
8919     aopOp(IC_JTCOND(ic),ic,FALSE);
8920     /* get the condition into accumulator */
8921     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
8922     MOVA(l);
8923     /* multiply by three */
8924     pic14_emitcode("add","a,acc");
8925     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
8926
8927     jtab = newiTempLabel(NULL);
8928     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
8929     pic14_emitcode("jmp","@a+dptr");
8930     pic14_emitcode("","%05d_DS_:",jtab->key+100);
8931
8932     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
8933     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
8934     emitSKPNC;
8935     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
8936     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
8937     emitpLabel(jtab->key);
8938
8939     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
8940
8941     /* now generate the jump labels */
8942     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
8943          jtab = setNextItem(IC_JTLABELS(ic))) {
8944         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
8945         emitpcode(POC_GOTO,popGetLabel(jtab->key));
8946         
8947     }
8948
8949 }
8950
8951 /*-----------------------------------------------------------------*/
8952 /* genMixedOperation - gen code for operators between mixed types  */
8953 /*-----------------------------------------------------------------*/
8954 /*
8955   TSD - Written for the PIC port - but this unfortunately is buggy.
8956   This routine is good in that it is able to efficiently promote 
8957   types to different (larger) sizes. Unfortunately, the temporary
8958   variables that are optimized out by this routine are sometimes
8959   used in other places. So until I know how to really parse the 
8960   iCode tree, I'm going to not be using this routine :(.
8961 */
8962 static int genMixedOperation (iCode *ic)
8963 {
8964 #if 0
8965   operand *result = IC_RESULT(ic);
8966   sym_link *ctype = operandType(IC_LEFT(ic));
8967   operand *right = IC_RIGHT(ic);
8968   int ret = 0;
8969   int big,small;
8970   int offset;
8971
8972   iCode *nextic;
8973   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
8974
8975   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
8976
8977   nextic = ic->next;
8978   if(!nextic)
8979     return 0;
8980
8981   nextright = IC_RIGHT(nextic);
8982   nextleft  = IC_LEFT(nextic);
8983   nextresult = IC_RESULT(nextic);
8984
8985   aopOp(right,ic,FALSE);
8986   aopOp(result,ic,FALSE);
8987   aopOp(nextright,  nextic, FALSE);
8988   aopOp(nextleft,   nextic, FALSE);
8989   aopOp(nextresult, nextic, FALSE);
8990
8991   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
8992
8993     operand *t = right;
8994     right = nextright;
8995     nextright = t; 
8996
8997     pic14_emitcode(";remove right +","");
8998
8999   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9000 /*
9001     operand *t = right;
9002     right = nextleft;
9003     nextleft = t; 
9004 */
9005     pic14_emitcode(";remove left +","");
9006   } else
9007     return 0;
9008
9009   big = AOP_SIZE(nextleft);
9010   small = AOP_SIZE(nextright);
9011
9012   switch(nextic->op) {
9013
9014   case '+':
9015     pic14_emitcode(";optimize a +","");
9016     /* if unsigned or not an integral type */
9017     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9018       pic14_emitcode(";add a bit to something","");
9019     } else {
9020
9021       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9022
9023       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9024         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9025         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9026       } else
9027         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9028
9029       offset = 0;
9030       while(--big) {
9031
9032         offset++;
9033
9034         if(--small) {
9035           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9036             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9037             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9038           }
9039
9040           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9041           emitSKPNC;
9042           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9043                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9044                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9045           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9046           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9047
9048         } else {
9049           pic14_emitcode("rlf","known_zero,w");
9050
9051           /*
9052             if right is signed
9053               btfsc  right,7
9054                addlw ff
9055           */
9056           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9057             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9058             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9059           } else {
9060             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9061           }
9062         }
9063       }
9064       ret = 1;
9065     }
9066   }
9067   ret = 1;
9068
9069 release:
9070   freeAsmop(right,NULL,ic,TRUE);
9071   freeAsmop(result,NULL,ic,TRUE);
9072   freeAsmop(nextright,NULL,ic,TRUE);
9073   freeAsmop(nextleft,NULL,ic,TRUE);
9074   if(ret)
9075     nextic->generated = 1;
9076
9077   return ret;
9078 #else
9079   return 0;
9080 #endif
9081 }
9082 /*-----------------------------------------------------------------*/
9083 /* genCast - gen code for casting                                  */
9084 /*-----------------------------------------------------------------*/
9085 static void genCast (iCode *ic)
9086 {
9087     operand *result = IC_RESULT(ic);
9088     sym_link *ctype = operandType(IC_LEFT(ic));
9089     sym_link *rtype = operandType(IC_RIGHT(ic));
9090     operand *right = IC_RIGHT(ic);
9091     int size, offset ;
9092
9093     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9094     /* if they are equivalent then do nothing */
9095     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9096         return ;
9097
9098     aopOp(right,ic,FALSE) ;
9099     aopOp(result,ic,FALSE);
9100
9101     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9102
9103     /* if the result is a bit */
9104     if (AOP_TYPE(result) == AOP_CRY) {
9105         /* if the right size is a literal then
9106         we know what the value is */
9107       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9108         if (AOP_TYPE(right) == AOP_LIT) {
9109
9110           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9111                       popGet(AOP(result),0));
9112
9113             if (((int) operandLitValue(right))) 
9114               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9115                        AOP(result)->aopu.aop_dir,
9116                        AOP(result)->aopu.aop_dir);
9117             else
9118               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9119                        AOP(result)->aopu.aop_dir,
9120                        AOP(result)->aopu.aop_dir);
9121
9122             goto release;
9123         }
9124
9125         /* the right is also a bit variable */
9126         if (AOP_TYPE(right) == AOP_CRY) {
9127
9128           emitCLRC;
9129           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9130
9131           pic14_emitcode("clrc","");
9132           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9133                    AOP(right)->aopu.aop_dir,
9134                    AOP(right)->aopu.aop_dir);
9135             aopPut(AOP(result),"c",0);
9136             goto release ;
9137         }
9138
9139         /* we need to or */
9140         if (AOP_TYPE(right) == AOP_REG) {
9141           emitpcode(POC_BCF,    popGet(AOP(result),0));
9142           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9143           emitpcode(POC_BSF,    popGet(AOP(result),0));
9144         }
9145         pic14_toBoolean(right);
9146         aopPut(AOP(result),"a",0);
9147         goto release ;
9148     }
9149
9150     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9151       int offset = 1;
9152       size = AOP_SIZE(result);
9153
9154       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9155
9156       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9157       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9158       emitpcode(POC_INCF,   popGet(AOP(result),0));
9159
9160       while (size--)
9161         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9162
9163       goto release;
9164     }
9165
9166     /* if they are the same size : or less */
9167     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9168
9169         /* if they are in the same place */
9170       if (pic14_sameRegs(AOP(right),AOP(result)))
9171         goto release;
9172
9173       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9174       if (IS_PTR_CONST(rtype))
9175         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9176       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9177         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9178
9179         /* if they in different places then copy */
9180         size = AOP_SIZE(result);
9181         offset = 0 ;
9182         while (size--) {
9183           if(AOP_TYPE(right) == AOP_IMMD)
9184             emitpcode(POC_MOVLW, popGetImmd(AOP(right)->aopu.aop_dir,offset));
9185           else
9186             emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9187           emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9188
9189           //aopPut(AOP(result),
9190           // aopGet(AOP(right),offset,FALSE,FALSE),
9191           // offset);
9192
9193           offset++;
9194         }
9195         goto release;
9196     }
9197
9198
9199     /* if the result is of type pointer */
9200     if (IS_PTR(ctype)) {
9201
9202         int p_type;
9203         sym_link *type = operandType(right);
9204         sym_link *etype = getSpec(type);
9205       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9206
9207         /* pointer to generic pointer */
9208         if (IS_GENPTR(ctype)) {
9209             char *l = zero;
9210             
9211             if (IS_PTR(type)) 
9212                 p_type = DCL_TYPE(type);
9213             else {
9214                 /* we have to go by the storage class */
9215                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9216
9217 /*              if (SPEC_OCLS(etype)->codesp )  */
9218 /*                  p_type = CPOINTER ;  */
9219 /*              else */
9220 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9221 /*                      p_type = FPOINTER ; */
9222 /*                  else */
9223 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9224 /*                          p_type = PPOINTER; */
9225 /*                      else */
9226 /*                          if (SPEC_OCLS(etype) == idata ) */
9227 /*                              p_type = IPOINTER ; */
9228 /*                          else */
9229 /*                              p_type = POINTER ; */
9230             }
9231                 
9232             /* the first two bytes are known */
9233             size = GPTRSIZE - 1; 
9234             offset = 0 ;
9235             while (size--) {
9236               if(offset < AOP_SIZE(right))
9237                 aopPut(AOP(result),
9238                        aopGet(AOP(right),offset,FALSE,FALSE),
9239                        offset);
9240               else
9241                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9242               offset++;
9243             }
9244             /* the last byte depending on type */
9245             switch (p_type) {
9246             case IPOINTER:
9247             case POINTER:
9248                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9249                 break;
9250             case FPOINTER:
9251               pic14_emitcode(";BUG!? ","%d",__LINE__);
9252                 l = one;
9253                 break;
9254             case CPOINTER:
9255               pic14_emitcode(";BUG!? ","%d",__LINE__);
9256                 l = "#0x02";
9257                 break;                          
9258             case PPOINTER:
9259               pic14_emitcode(";BUG!? ","%d",__LINE__);
9260                 l = "#0x03";
9261                 break;
9262                 
9263             default:
9264                 /* this should never happen */
9265                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9266                        "got unknown pointer type");
9267                 exit(1);
9268             }
9269             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9270             goto release ;
9271         }
9272         
9273         /* just copy the pointers */
9274         size = AOP_SIZE(result);
9275         offset = 0 ;
9276         while (size--) {
9277             aopPut(AOP(result),
9278                    aopGet(AOP(right),offset,FALSE,FALSE),
9279                    offset);
9280             offset++;
9281         }
9282         goto release ;
9283     }
9284     
9285
9286
9287     /* so we now know that the size of destination is greater
9288     than the size of the source.
9289     Now, if the next iCode is an operator then we might be
9290     able to optimize the operation without performing a cast.
9291     */
9292     if(genMixedOperation(ic))
9293       goto release;
9294
9295     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9296     
9297     /* we move to result for the size of source */
9298     size = AOP_SIZE(right);
9299     offset = 0 ;
9300     while (size--) {
9301       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9302       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9303       offset++;
9304     }
9305
9306     /* now depending on the sign of the destination */
9307     size = AOP_SIZE(result) - AOP_SIZE(right);
9308     /* if unsigned or not an integral type */
9309     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9310       while (size--)
9311         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9312     } else {
9313       /* we need to extend the sign :{ */
9314
9315       if(size == 1) {
9316         /* Save one instruction of casting char to int */
9317         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9318         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9319         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9320       } else {
9321         emitpcodeNULLop(POC_CLRW);
9322
9323         if(offset)
9324           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9325         else
9326           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9327         
9328         emitpcode(POC_MOVLW,   popGetLit(0xff));
9329
9330         while (size--)
9331           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9332       }
9333     }
9334
9335 release:
9336     freeAsmop(right,NULL,ic,TRUE);
9337     freeAsmop(result,NULL,ic,TRUE);
9338
9339 }
9340
9341 /*-----------------------------------------------------------------*/
9342 /* genDjnz - generate decrement & jump if not zero instrucion      */
9343 /*-----------------------------------------------------------------*/
9344 static int genDjnz (iCode *ic, iCode *ifx)
9345 {
9346     symbol *lbl, *lbl1;
9347     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9348
9349     if (!ifx)
9350         return 0;
9351     
9352     /* if the if condition has a false label
9353        then we cannot save */
9354     if (IC_FALSE(ifx))
9355         return 0;
9356
9357     /* if the minus is not of the form 
9358        a = a - 1 */
9359     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9360         !IS_OP_LITERAL(IC_RIGHT(ic)))
9361         return 0;
9362
9363     if (operandLitValue(IC_RIGHT(ic)) != 1)
9364         return 0;
9365
9366     /* if the size of this greater than one then no
9367        saving */
9368     if (getSize(operandType(IC_RESULT(ic))) > 1)
9369         return 0;
9370
9371     /* otherwise we can save BIG */
9372     lbl = newiTempLabel(NULL);
9373     lbl1= newiTempLabel(NULL);
9374
9375     aopOp(IC_RESULT(ic),ic,FALSE);
9376     
9377     if (IS_AOP_PREG(IC_RESULT(ic))) {
9378         pic14_emitcode("dec","%s",
9379                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9380         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9381         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9382     } else {    
9383
9384
9385       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9386       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9387
9388       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9389       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9390
9391     }
9392 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9393 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9394 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9395 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9396
9397     
9398     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9399     ifx->generated = 1;
9400     return 1;
9401 }
9402
9403 /*-----------------------------------------------------------------*/
9404 /* genReceive - generate code for a receive iCode                  */
9405 /*-----------------------------------------------------------------*/
9406 static void genReceive (iCode *ic)
9407 {    
9408   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9409
9410   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9411       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9412         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9413
9414     int size = getSize(operandType(IC_RESULT(ic)));
9415     int offset =  fReturnSizePic - size;
9416     while (size--) {
9417       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9418                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9419       offset++;
9420     }
9421     aopOp(IC_RESULT(ic),ic,FALSE);  
9422     size = AOP_SIZE(IC_RESULT(ic));
9423     offset = 0;
9424     while (size--) {
9425       pic14_emitcode ("pop","acc");
9426       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9427     }
9428         
9429   } else {
9430     _G.accInUse++;
9431     aopOp(IC_RESULT(ic),ic,FALSE);  
9432     _G.accInUse--;
9433     assignResultValue(IC_RESULT(ic));   
9434   }
9435
9436   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9437 }
9438
9439 /*-----------------------------------------------------------------*/
9440 /* genpic14Code - generate code for pic14 based controllers        */
9441 /*-----------------------------------------------------------------*/
9442 /*
9443  * At this point, ralloc.c has gone through the iCode and attempted
9444  * to optimize in a way suitable for a PIC. Now we've got to generate
9445  * PIC instructions that correspond to the iCode.
9446  *
9447  * Once the instructions are generated, we'll pass through both the
9448  * peep hole optimizer and the pCode optimizer.
9449  *-----------------------------------------------------------------*/
9450
9451 void genpic14Code (iCode *lic)
9452 {
9453     iCode *ic;
9454     int cln = 0;
9455
9456     lineHead = lineCurr = NULL;
9457
9458     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9459     addpBlock(pb);
9460
9461     /* if debug information required */
9462     if (options.debug && currFunc) { 
9463       if (currFunc) {
9464         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9465         _G.debugLine = 1;
9466         if (IS_STATIC(currFunc->etype)) {
9467           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9468           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9469         } else {
9470           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9471           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9472         }
9473         _G.debugLine = 0;
9474       }
9475     }
9476
9477
9478     for (ic = lic ; ic ; ic = ic->next ) {
9479
9480       DEBUGpic14_emitcode(";ic","");
9481         if ( cln != ic->lineno ) {
9482             if ( options.debug ) {
9483                 _G.debugLine = 1;
9484                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9485                          FileBaseName(ic->filename),ic->lineno,
9486                          ic->level,ic->block);
9487                 _G.debugLine = 0;
9488             }
9489             pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9490             pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9491                             printCLine(ic->filename, ic->lineno));
9492
9493             cln = ic->lineno ;
9494         }
9495         /* if the result is marked as
9496            spilt and rematerializable or code for
9497            this has already been generated then
9498            do nothing */
9499         if (resultRemat(ic) || ic->generated ) 
9500             continue ;
9501         
9502         /* depending on the operation */
9503         switch (ic->op) {
9504         case '!' :
9505             genNot(ic);
9506             break;
9507             
9508         case '~' :
9509             genCpl(ic);
9510             break;
9511             
9512         case UNARYMINUS:
9513             genUminus (ic);
9514             break;
9515             
9516         case IPUSH:
9517             genIpush (ic);
9518             break;
9519             
9520         case IPOP:
9521             /* IPOP happens only when trying to restore a 
9522                spilt live range, if there is an ifx statement
9523                following this pop then the if statement might
9524                be using some of the registers being popped which
9525                would destory the contents of the register so
9526                we need to check for this condition and handle it */
9527             if (ic->next            && 
9528                 ic->next->op == IFX &&
9529                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9530                 genIfx (ic->next,ic);
9531             else
9532                 genIpop (ic);
9533             break; 
9534             
9535         case CALL:
9536             genCall (ic);
9537             break;
9538             
9539         case PCALL:
9540             genPcall (ic);
9541             break;
9542             
9543         case FUNCTION:
9544             genFunction (ic);
9545             break;
9546             
9547         case ENDFUNCTION:
9548             genEndFunction (ic);
9549             break;
9550             
9551         case RETURN:
9552             genRet (ic);
9553             break;
9554             
9555         case LABEL:
9556             genLabel (ic);
9557             break;
9558             
9559         case GOTO:
9560             genGoto (ic);
9561             break;
9562             
9563         case '+' :
9564             genPlus (ic) ;
9565             break;
9566             
9567         case '-' :
9568             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9569                 genMinus (ic);
9570             break;
9571             
9572         case '*' :
9573             genMult (ic);
9574             break;
9575             
9576         case '/' :
9577             genDiv (ic) ;
9578             break;
9579             
9580         case '%' :
9581             genMod (ic);
9582             break;
9583             
9584         case '>' :
9585             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9586             break;
9587             
9588         case '<' :
9589             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9590             break;
9591             
9592         case LE_OP:
9593         case GE_OP:
9594         case NE_OP:
9595             
9596             /* note these two are xlated by algebraic equivalence
9597                during parsing SDCC.y */
9598             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9599                    "got '>=' or '<=' shouldn't have come here");
9600             break;      
9601             
9602         case EQ_OP:
9603             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9604             break;          
9605             
9606         case AND_OP:
9607             genAndOp (ic);
9608             break;
9609             
9610         case OR_OP:
9611             genOrOp (ic);
9612             break;
9613             
9614         case '^' :
9615             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9616             break;
9617             
9618         case '|' :
9619                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9620             break;
9621             
9622         case BITWISEAND:
9623             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9624             break;
9625             
9626         case INLINEASM:
9627             genInline (ic);
9628             break;
9629             
9630         case RRC:
9631             genRRC (ic);
9632             break;
9633             
9634         case RLC:
9635             genRLC (ic);
9636             break;
9637             
9638         case GETHBIT:
9639             genGetHbit (ic);
9640             break;
9641             
9642         case LEFT_OP:
9643             genLeftShift (ic);
9644             break;
9645             
9646         case RIGHT_OP:
9647             genRightShift (ic);
9648             break;
9649             
9650         case GET_VALUE_AT_ADDRESS:
9651             genPointerGet(ic);
9652             break;
9653             
9654         case '=' :
9655             if (POINTER_SET(ic))
9656                 genPointerSet(ic);
9657             else
9658                 genAssign(ic);
9659             break;
9660             
9661         case IFX:
9662             genIfx (ic,NULL);
9663             break;
9664             
9665         case ADDRESS_OF:
9666             genAddrOf (ic);
9667             break;
9668             
9669         case JUMPTABLE:
9670             genJumpTab (ic);
9671             break;
9672             
9673         case CAST:
9674             genCast (ic);
9675             break;
9676             
9677         case RECEIVE:
9678             genReceive(ic);
9679             break;
9680             
9681         case SEND:
9682             addSet(&_G.sendSet,ic);
9683             break;
9684
9685         default :
9686             ic = ic;
9687         }
9688     }
9689     
9690
9691     /* now we are ready to call the 
9692        peep hole optimizer */
9693     if (!options.nopeep) {
9694       peepHole (&lineHead);
9695     }
9696     /* now do the actual printing */
9697     printLine (lineHead,codeOutFile);
9698
9699 #ifdef PCODE_DEBUG
9700     DFPRINTF((stderr,"printing pBlock\n\n"));
9701     printpBlock(stdout,pb);
9702 #endif
9703
9704     return;
9705 }