Fixed fatal infinite loop in pcode optimizer.
[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, int index);
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_PCODE);
550
551     aop->aopu.pcop = popGetImmd(sym->rname,0,0);
552     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
553     PCOI(aop->aopu.pcop)->index = 0;
554
555     DEBUGpic14_emitcode(";"," rname %s, val %d, const = %d",
556                         sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
557
558     allocDirReg (IC_LEFT(ic));
559
560     aop->size = FPTRSIZE; 
561 /*
562     DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
563     sym->aop = aop = newAsmop(AOP_DPTR);
564     pic14_emitcode ("mov","dptr,#%s", sym->rname);
565     aop->size = getSize(sym->type);
566
567     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
568 */
569
570     /* if it is in code space */
571     if (IN_CODESPACE(space))
572         aop->code = 1;
573
574     return aop;     
575 }
576
577 /*-----------------------------------------------------------------*/
578 /* aopForRemat - rematerialzes an object                           */
579 /*-----------------------------------------------------------------*/
580 static asmop *aopForRemat (operand *op) // x symbol *sym)
581 {
582   symbol *sym = OP_SYMBOL(op);
583   iCode *ic = NULL;
584   asmop *aop = newAsmop(AOP_PCODE);
585   int val = 0;
586   int offset = 0;
587
588   ic = sym->rematiCode;
589
590     DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
591
592     for (;;) {
593       if (ic->op == '+') {
594         val += (int) operandLitValue(IC_RIGHT(ic));
595       } else if (ic->op == '-') {
596         val -= (int) operandLitValue(IC_RIGHT(ic));
597       } else
598             break;
599         
600         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
601     }
602
603     offset = OP_SYMBOL(IC_LEFT(ic))->offset;
604     aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
605     PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
606     PCOI(aop->aopu.pcop)->index = val;
607
608     DEBUGpic14_emitcode(";"," rname %s, val %d, const = %d",
609                         OP_SYMBOL(IC_LEFT(ic))->rname,
610                         val, IS_PTR_CONST(operandType(op)));
611
612     //    DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
613
614     allocDirReg (IC_LEFT(ic));
615
616     return aop;        
617 }
618
619 int aopIdx (asmop *aop, int offset)
620 {
621   if(!aop)
622     return -1;
623
624   if(aop->type !=  AOP_REG)
625     return -2;
626         
627   return aop->aopu.aop_reg[offset]->rIdx;
628
629 }
630 /*-----------------------------------------------------------------*/
631 /* regsInCommon - two operands have some registers in common       */
632 /*-----------------------------------------------------------------*/
633 static bool regsInCommon (operand *op1, operand *op2)
634 {
635     symbol *sym1, *sym2;
636     int i;
637
638     /* if they have registers in common */
639     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
640         return FALSE ;
641
642     sym1 = OP_SYMBOL(op1);
643     sym2 = OP_SYMBOL(op2);
644
645     if (sym1->nRegs == 0 || sym2->nRegs == 0)
646         return FALSE ;
647
648     for (i = 0 ; i < sym1->nRegs ; i++) {
649         int j;
650         if (!sym1->regs[i])
651             continue ;
652
653         for (j = 0 ; j < sym2->nRegs ;j++ ) {
654             if (!sym2->regs[j])
655                 continue ;
656
657             if (sym2->regs[j] == sym1->regs[i])
658                 return TRUE ;
659         }
660     }
661
662     return FALSE ;
663 }
664
665 /*-----------------------------------------------------------------*/
666 /* operandsEqu - equivalent                                        */
667 /*-----------------------------------------------------------------*/
668 static bool operandsEqu ( operand *op1, operand *op2)
669 {
670     symbol *sym1, *sym2;
671
672     /* if they not symbols */
673     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
674         return FALSE;
675
676     sym1 = OP_SYMBOL(op1);
677     sym2 = OP_SYMBOL(op2);
678
679     /* if both are itemps & one is spilt
680        and the other is not then false */
681     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
682         sym1->isspilt != sym2->isspilt )
683         return FALSE ;
684
685     /* if they are the same */
686     if (sym1 == sym2)
687         return TRUE ;
688
689     if (strcmp(sym1->rname,sym2->rname) == 0)
690         return TRUE;
691
692
693     /* if left is a tmp & right is not */
694     if (IS_ITEMP(op1)  && 
695         !IS_ITEMP(op2) &&
696         sym1->isspilt  &&
697         (sym1->usl.spillLoc == sym2))
698         return TRUE;
699
700     if (IS_ITEMP(op2)  && 
701         !IS_ITEMP(op1) &&
702         sym2->isspilt  &&
703         sym1->level > 0 &&
704         (sym2->usl.spillLoc == sym1))
705         return TRUE ;
706
707     return FALSE ;
708 }
709
710 /*-----------------------------------------------------------------*/
711 /* pic14_sameRegs - two asmops have the same registers                   */
712 /*-----------------------------------------------------------------*/
713 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
714 {
715     int i;
716
717     if (aop1 == aop2)
718         return TRUE ;
719
720     if (aop1->type != AOP_REG ||
721         aop2->type != AOP_REG )
722         return FALSE ;
723
724     if (aop1->size != aop2->size )
725         return FALSE ;
726
727     for (i = 0 ; i < aop1->size ; i++ )
728         if (aop1->aopu.aop_reg[i] !=
729             aop2->aopu.aop_reg[i] )
730             return FALSE ;
731
732     return TRUE ;
733 }
734
735 /*-----------------------------------------------------------------*/
736 /* aopOp - allocates an asmop for an operand  :                    */
737 /*-----------------------------------------------------------------*/
738 void aopOp (operand *op, iCode *ic, bool result)
739 {
740     asmop *aop;
741     symbol *sym;
742     int i;
743
744     if (!op)
745         return ;
746
747     //    DEBUGpic14_emitcode(";","%d",__LINE__);
748     /* if this a literal */
749     if (IS_OP_LITERAL(op)) {
750         op->aop = aop = newAsmop(AOP_LIT);
751         aop->aopu.aop_lit = op->operand.valOperand;
752         aop->size = getSize(operandType(op));
753         return;
754     }
755
756     {
757       sym_link *type = operandType(op);
758       if(IS_PTR_CONST(type))
759         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
760     }
761
762     /* if already has a asmop then continue */
763     if (op->aop)
764         return ;
765
766     /* if the underlying symbol has a aop */
767     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
768       DEBUGpic14_emitcode(";","%d",__LINE__);
769         op->aop = OP_SYMBOL(op)->aop;
770         return;
771     }
772
773     /* if this is a true symbol */
774     if (IS_TRUE_SYMOP(op)) {    
775       //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
776       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
777       return ;
778     }
779
780     /* this is a temporary : this has
781     only four choices :
782     a) register
783     b) spillocation
784     c) rematerialize 
785     d) conditional   
786     e) can be a return use only */
787
788     sym = OP_SYMBOL(op);
789
790
791     /* if the type is a conditional */
792     if (sym->regType == REG_CND) {
793         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
794         aop->size = 0;
795         return;
796     }
797
798     /* if it is spilt then two situations
799     a) is rematerialize 
800     b) has a spill location */
801     if (sym->isspilt || sym->nRegs == 0) {
802
803       DEBUGpic14_emitcode(";","%d",__LINE__);
804         /* rematerialize it NOW */
805         if (sym->remat) {
806
807             sym->aop = op->aop = aop =
808                                       aopForRemat (op);
809             aop->size = getSize(sym->type);
810             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
811             return;
812         }
813
814         if (sym->accuse) {
815             int i;
816             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
817             aop->size = getSize(sym->type);
818             for ( i = 0 ; i < 2 ; i++ )
819                 aop->aopu.aop_str[i] = accUse[i];
820             DEBUGpic14_emitcode(";","%d",__LINE__);
821             return;  
822         }
823
824         if (sym->ruonly ) {
825             unsigned i;
826             aop = op->aop = sym->aop = newAsmop(AOP_STR);
827             aop->size = getSize(sym->type);
828             for ( i = 0 ; i < fReturnSizePic ; i++ )
829               aop->aopu.aop_str[i] = fReturn[i];
830             DEBUGpic14_emitcode(";","%d",__LINE__);
831             return;
832         }
833
834         /* else spill location  */
835         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
836             /* force a new aop if sizes differ */
837             sym->usl.spillLoc->aop = NULL;
838         }
839         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
840                             __FUNCTION__,__LINE__,
841                             sym->usl.spillLoc->rname,
842                             sym->rname, sym->usl.spillLoc->offset);
843         // X sym->aop = op->aop = aop = aopForSym(ic,sym->usl.spillLoc,result);
844         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
845         aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
846         //allocDirReg (IC_LEFT(ic));
847         aop->size = getSize(sym->type);
848
849         return;
850     }
851
852     {
853       sym_link *type = operandType(op);
854       if(IS_PTR_CONST(type)) 
855         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
856     }
857
858     /* must be in a register */
859     sym->aop = op->aop = aop = newAsmop(AOP_REG);
860     aop->size = sym->nRegs;
861     for ( i = 0 ; i < sym->nRegs ;i++)
862         aop->aopu.aop_reg[i] = sym->regs[i];
863 }
864
865 /*-----------------------------------------------------------------*/
866 /* freeAsmop - free up the asmop given to an operand               */
867 /*----------------------------------------------------------------*/
868 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
869 {   
870     asmop *aop ;
871
872     if (!op)
873         aop = aaop;
874     else 
875         aop = op->aop;
876
877     if (!aop)
878         return ;
879
880     if (aop->freed)
881         goto dealloc; 
882
883     aop->freed = 1;
884
885     /* depending on the asmop type only three cases need work AOP_RO
886        , AOP_R1 && AOP_STK */
887 #if 0
888     switch (aop->type) {
889         case AOP_R0 :
890             if (_G.r0Pushed ) {
891                 if (pop) {
892                     pic14_emitcode ("pop","ar0");     
893                     _G.r0Pushed--;
894                 }
895             }
896             bitVectUnSetBit(ic->rUsed,R0_IDX);
897             break;
898
899         case AOP_R1 :
900             if (_G.r1Pushed ) {
901                 if (pop) {
902                     pic14_emitcode ("pop","ar1");
903                     _G.r1Pushed--;
904                 }
905             }
906             bitVectUnSetBit(ic->rUsed,R1_IDX);          
907             break;
908
909         case AOP_STK :
910         {
911             int sz = aop->size;    
912             int stk = aop->aopu.aop_stk + aop->size;
913             bitVectUnSetBit(ic->rUsed,R0_IDX);
914             bitVectUnSetBit(ic->rUsed,R1_IDX);          
915
916             getFreePtr(ic,&aop,FALSE);
917             
918             if (options.stack10bit)
919             {
920                 /* I'm not sure what to do here yet... */
921                 /* #STUB */
922                 fprintf(stderr, 
923                         "*** Warning: probably generating bad code for "
924                         "10 bit stack mode.\n");
925             }
926             
927             if (stk) {
928                 pic14_emitcode ("mov","a,_bp");
929                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
930                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
931             } else {
932                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
933             }
934
935             while (sz--) {
936                 pic14_emitcode("pop","acc");
937                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
938                 if (!sz) break;
939                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
940             }
941             op->aop = aop;
942             freeAsmop(op,NULL,ic,TRUE);
943             if (_G.r0Pushed) {
944                 pic14_emitcode("pop","ar0");
945                 _G.r0Pushed--;
946             }
947
948             if (_G.r1Pushed) {
949                 pic14_emitcode("pop","ar1");
950                 _G.r1Pushed--;
951             }       
952         }
953     }
954 #endif
955
956 dealloc:
957     /* all other cases just dealloc */
958     if (op ) {
959         op->aop = NULL;
960         if (IS_SYMOP(op)) {
961             OP_SYMBOL(op)->aop = NULL;    
962             /* if the symbol has a spill */
963             if (SPIL_LOC(op))
964                 SPIL_LOC(op)->aop = NULL;
965         }
966     }
967 }
968
969 /*-----------------------------------------------------------------*/
970 /* aopGet - for fetching value of the aop                          */
971 /*-----------------------------------------------------------------*/
972 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
973 {
974     char *s = buffer ;
975     char *rs;
976
977     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
978     /* offset is greater than
979     size then zero */
980     if (offset > (aop->size - 1) &&
981         aop->type != AOP_LIT)
982         return zero;
983
984     /* depending on type */
985     switch (aop->type) {
986         
987     case AOP_R0:
988     case AOP_R1:
989         DEBUGpic14_emitcode(";","%d",__LINE__);
990         /* if we need to increment it */       
991         while (offset > aop->coff) {        
992             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
993             aop->coff++;
994         }
995         
996         while (offset < aop->coff) {
997             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
998             aop->coff--;
999         }
1000         
1001         aop->coff = offset ;
1002         if (aop->paged) {
1003             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1004             return (dname ? "acc" : "a");
1005         }       
1006         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1007         rs = Safe_calloc(1,strlen(s)+1);
1008         strcpy(rs,s);   
1009         return rs;
1010         
1011     case AOP_DPTR:
1012     case AOP_DPTR2:
1013         DEBUGpic14_emitcode(";","%d",__LINE__);
1014     if (aop->type == AOP_DPTR2)
1015     {
1016         genSetDPTR(1);
1017     }
1018     
1019         while (offset > aop->coff) {
1020             pic14_emitcode ("inc","dptr");
1021             aop->coff++;
1022         }
1023         
1024         while (offset < aop->coff) {        
1025             pic14_emitcode("lcall","__decdptr");
1026             aop->coff--;
1027         }
1028         
1029         aop->coff = offset;
1030         if (aop->code) {
1031             pic14_emitcode("clr","a");
1032             pic14_emitcode("movc","a,@a+dptr");
1033         }
1034     else {
1035             pic14_emitcode("movx","a,@dptr");
1036     }
1037             
1038     if (aop->type == AOP_DPTR2)
1039     {
1040         genSetDPTR(0);
1041     }
1042             
1043     return (dname ? "acc" : "a");
1044         
1045         
1046     case AOP_IMMD:
1047         if (bit16) 
1048             sprintf (s,"%s",aop->aopu.aop_immd);
1049         else
1050             if (offset) 
1051                 sprintf(s,"(%s >> %d)",
1052                         aop->aopu.aop_immd,
1053                         offset*8);
1054             else
1055                 sprintf(s,"%s",
1056                         aop->aopu.aop_immd);
1057         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1058         rs = Safe_calloc(1,strlen(s)+1);
1059         strcpy(rs,s);   
1060         return rs;
1061         
1062     case AOP_DIR:
1063       if (offset) {
1064         sprintf(s,"(%s + %d)",
1065                 aop->aopu.aop_dir,
1066                 offset);
1067         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1068       } else
1069             sprintf(s,"%s",aop->aopu.aop_dir);
1070         rs = Safe_calloc(1,strlen(s)+1);
1071         strcpy(rs,s);   
1072         return rs;
1073         
1074     case AOP_REG:
1075       //if (dname) 
1076       //    return aop->aopu.aop_reg[offset]->dname;
1077       //else
1078             return aop->aopu.aop_reg[offset]->name;
1079         
1080     case AOP_CRY:
1081       //pic14_emitcode(";","%d",__LINE__);
1082       return aop->aopu.aop_dir;
1083         
1084     case AOP_ACC:
1085         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1086         return "AOP_accumulator_bug";
1087
1088     case AOP_LIT:
1089         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1090         rs = Safe_calloc(1,strlen(s)+1);
1091         strcpy(rs,s);   
1092         return rs;
1093         
1094     case AOP_STR:
1095         DEBUGpic14_emitcode(";","%d",__LINE__);
1096         aop->coff = offset ;
1097         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1098             dname)
1099             return "acc";
1100         
1101         return aop->aopu.aop_str[offset];
1102         
1103     case AOP_PCODE:
1104       {
1105         pCodeOp *pcop = aop->aopu.pcop;
1106         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE",__LINE__);
1107         if(pcop->name) {
1108           DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1109           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1110           sprintf(s,"%s", pcop->name);
1111         } else
1112           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1113
1114       }
1115       rs = Safe_calloc(1,strlen(s)+1);
1116       strcpy(rs,s);   
1117       return rs;
1118
1119     }
1120
1121     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1122            "aopget got unsupported aop->type");
1123     exit(0);
1124 }
1125
1126
1127 /*-----------------------------------------------------------------*/
1128 /* popGetTempReg - create a new temporary pCodeOp                  */
1129 /*-----------------------------------------------------------------*/
1130 pCodeOp *popGetTempReg(void)
1131 {
1132
1133   pCodeOp *pcop;
1134
1135   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1136   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1137     PCOR(pcop)->r->wasUsed=1;
1138     PCOR(pcop)->r->isFree=0;
1139   }
1140
1141   return pcop;
1142 }
1143
1144 /*-----------------------------------------------------------------*/
1145 /* popGetTempReg - create a new temporary pCodeOp                  */
1146 /*-----------------------------------------------------------------*/
1147 void popReleaseTempReg(pCodeOp *pcop)
1148 {
1149
1150   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1151     PCOR(pcop)->r->isFree = 1;
1152
1153 }
1154 /*-----------------------------------------------------------------*/
1155 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1156 /*-----------------------------------------------------------------*/
1157 pCodeOp *popGetLabel(unsigned int key)
1158 {
1159
1160   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1161
1162   if(key>max_key)
1163     max_key = key;
1164
1165   return newpCodeOpLabel(NULL,key+100+labelOffset);
1166 }
1167
1168 /*-----------------------------------------------------------------*/
1169 /* popCopyReg - copy a pcode operator                              */
1170 /*-----------------------------------------------------------------*/
1171 pCodeOp *popCopyReg(pCodeOpReg *pc)
1172 {
1173   pCodeOpReg *pcor;
1174
1175   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1176   pcor->pcop.type = pc->pcop.type;
1177   if(pc->pcop.name) {
1178     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1179       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1180   } else
1181     pcor->pcop.name = NULL;
1182
1183   pcor->r = pc->r;
1184   pcor->rIdx = pc->rIdx;
1185   pcor->r->wasUsed=1;
1186
1187   //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1188
1189   return PCOP(pcor);
1190 }
1191 /*-----------------------------------------------------------------*/
1192 /* popGet - asm operator to pcode operator conversion              */
1193 /*-----------------------------------------------------------------*/
1194 pCodeOp *popGetLit(unsigned int lit)
1195 {
1196
1197   return newpCodeOpLit(lit);
1198 }
1199
1200
1201 /*-----------------------------------------------------------------*/
1202 /* popGetImmd - asm operator to pcode immediate conversion         */
1203 /*-----------------------------------------------------------------*/
1204 pCodeOp *popGetImmd(char *name, unsigned int offset, int index)
1205 {
1206
1207   return newpCodeOpImmd(name, offset,index, 0);
1208 }
1209
1210
1211 /*-----------------------------------------------------------------*/
1212 /* popGet - asm operator to pcode operator conversion              */
1213 /*-----------------------------------------------------------------*/
1214 pCodeOp *popGetWithString(char *str)
1215 {
1216   pCodeOp *pcop;
1217
1218
1219   if(!str) {
1220     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1221     exit (1);
1222   }
1223
1224   pcop = newpCodeOp(str,PO_STR);
1225
1226   return pcop;
1227 }
1228
1229 pCodeOp *popRegFromString(char *str)
1230 {
1231
1232   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOp) );
1233   pcop->type = PO_DIR;
1234
1235   DEBUGpic14_emitcode(";","%d",__LINE__);
1236   pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1237
1238   return pcop;
1239 }
1240
1241 pCodeOp *popRegFromIdx(int rIdx)
1242 {
1243   pCodeOp *pcop;
1244
1245   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1246                        __FUNCTION__,__LINE__,rIdx);
1247
1248   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1249
1250   PCOR(pcop)->rIdx = rIdx;
1251   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1252   PCOR(pcop)->r->isFree = 0;
1253   PCOR(pcop)->r->wasUsed = 1;
1254
1255   pcop->type = PCOR(pcop)->r->pc_type;
1256
1257
1258   return pcop;
1259 }
1260 /*-----------------------------------------------------------------*/
1261 /* popGet - asm operator to pcode operator conversion              */
1262 /*-----------------------------------------------------------------*/
1263 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1264 {
1265   //char *s = buffer ;
1266     //char *rs;
1267
1268     pCodeOp *pcop;
1269
1270     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1271     /* offset is greater than
1272     size then zero */
1273
1274     if (offset > (aop->size - 1) &&
1275         aop->type != AOP_LIT)
1276       return NULL;  //zero;
1277
1278     /* depending on type */
1279     switch (aop->type) {
1280         
1281     case AOP_R0:
1282     case AOP_R1:
1283     case AOP_DPTR:
1284     case AOP_DPTR2:
1285     case AOP_ACC:
1286         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1287         return NULL;
1288         
1289     case AOP_IMMD:
1290       DEBUGpic14_emitcode(";","%d",__LINE__);
1291       return popGetImmd(aop->aopu.aop_immd,offset,0);
1292
1293     case AOP_DIR:
1294         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1295         pcop->type = PO_DIR;
1296
1297         /*
1298         if (offset)
1299             sprintf(s,"(%s + %d)",
1300                     aop->aopu.aop_dir,
1301                     offset);
1302         else
1303             sprintf(s,"%s",aop->aopu.aop_dir);
1304         pcop->name = Safe_calloc(1,strlen(s)+1);
1305         strcpy(pcop->name,s);   
1306         */
1307         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1308         strcpy(pcop->name,aop->aopu.aop_dir);   
1309         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1310         if(PCOR(pcop)->r == NULL) {
1311           //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1312           PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1313         } 
1314
1315       DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1316         PCOR(pcop)->instance = offset;
1317
1318         return pcop;
1319         
1320     case AOP_REG:
1321       {
1322         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1323
1324         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1325         PCOR(pcop)->rIdx = rIdx;
1326         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1327         PCOR(pcop)->instance = offset;
1328         pcop->type = PCOR(pcop)->r->pc_type;
1329         //rs = aop->aopu.aop_reg[offset]->name;
1330         //DEBUGpic14_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1331         return pcop;
1332       }
1333
1334     case AOP_CRY:
1335       pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1336       PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1337       //if(PCOR(pcop)->r == NULL)
1338       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1339       return pcop;
1340         
1341     case AOP_LIT:
1342       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1343
1344     case AOP_STR:
1345       DEBUGpic14_emitcode(";","%d",__LINE__);
1346       return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1347       /*
1348       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1349       PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1350       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1351       pcop->type = PCOR(pcop)->r->pc_type;
1352       pcop->name = PCOR(pcop)->r->name;
1353
1354       return pcop;
1355       */
1356
1357     case AOP_PCODE:
1358       DEBUGpic14_emitcode(";","popGet AOP_PCODE%d",__LINE__);
1359       pcop = pCodeOpCopy(aop->aopu.pcop);
1360       PCOI(pcop)->offset = offset;
1361       return pcop;
1362     }
1363
1364     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1365            "popGet got unsupported aop->type");
1366     exit(0);
1367 }
1368 /*-----------------------------------------------------------------*/
1369 /* aopPut - puts a string for a aop                                */
1370 /*-----------------------------------------------------------------*/
1371 void aopPut (asmop *aop, char *s, int offset)
1372 {
1373     char *d = buffer ;
1374     symbol *lbl ;
1375
1376     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1377
1378     if (aop->size && offset > ( aop->size - 1)) {
1379         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1380                "aopPut got offset > aop->size");
1381         exit(0);
1382     }
1383
1384     /* will assign value to value */
1385     /* depending on where it is ofcourse */
1386     switch (aop->type) {
1387     case AOP_DIR:
1388       if (offset) {
1389         sprintf(d,"(%s + %d)",
1390                 aop->aopu.aop_dir,offset);
1391         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1392
1393       } else
1394             sprintf(d,"%s",aop->aopu.aop_dir);
1395         
1396         if (strcmp(d,s)) {
1397           DEBUGpic14_emitcode(";","%d",__LINE__);
1398           if(strcmp(s,"W"))
1399             pic14_emitcode("movf","%s,w",s);
1400           pic14_emitcode("movwf","%s",d);
1401
1402           if(strcmp(s,"W")) {
1403             pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1404             if(offset >= aop->size) {
1405               emitpcode(POC_CLRF,popGet(aop,offset));
1406               break;
1407             } else
1408               emitpcode(POC_MOVLW,popGetImmd(s,offset,0));
1409           }
1410
1411           emitpcode(POC_MOVWF,popGet(aop,offset));
1412
1413
1414         }
1415         break;
1416         
1417     case AOP_REG:
1418       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1419         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1420           /*
1421             if (*s == '@'           ||
1422                 strcmp(s,"r0") == 0 ||
1423                 strcmp(s,"r1") == 0 ||
1424                 strcmp(s,"r2") == 0 ||
1425                 strcmp(s,"r3") == 0 ||
1426                 strcmp(s,"r4") == 0 ||
1427                 strcmp(s,"r5") == 0 ||
1428                 strcmp(s,"r6") == 0 || 
1429                 strcmp(s,"r7") == 0 )
1430                 pic14_emitcode("mov","%s,%s  ; %d",
1431                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1432             else
1433           */
1434
1435           if(strcmp(s,"W"))
1436             pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1437
1438           pic14_emitcode("movwf","%s",
1439                    aop->aopu.aop_reg[offset]->name);
1440
1441           if(strcmp(s,"W")) {
1442             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1443             pcop->type = PO_GPR_REGISTER;
1444
1445             PCOR(pcop)->rIdx = -1;
1446             PCOR(pcop)->r = NULL;
1447
1448             DEBUGpic14_emitcode(";","%d",__LINE__);
1449             pcop->name = Safe_strdup(s);
1450             emitpcode(POC_MOVFW,pcop);
1451           }
1452           emitpcode(POC_MOVWF,popGet(aop,offset));
1453
1454         }
1455         break;
1456         
1457     case AOP_DPTR:
1458     case AOP_DPTR2:
1459     
1460     if (aop->type == AOP_DPTR2)
1461     {
1462         genSetDPTR(1);
1463     }
1464     
1465         if (aop->code) {
1466             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1467                    "aopPut writting to code space");
1468             exit(0);
1469         }
1470         
1471         while (offset > aop->coff) {
1472             aop->coff++;
1473             pic14_emitcode ("inc","dptr");
1474         }
1475         
1476         while (offset < aop->coff) {
1477             aop->coff-- ;
1478             pic14_emitcode("lcall","__decdptr");
1479         }
1480         
1481         aop->coff = offset;
1482         
1483         /* if not in accumulater */
1484         MOVA(s);        
1485         
1486         pic14_emitcode ("movx","@dptr,a");
1487         
1488     if (aop->type == AOP_DPTR2)
1489     {
1490         genSetDPTR(0);
1491     }
1492         break;
1493         
1494     case AOP_R0:
1495     case AOP_R1:
1496         while (offset > aop->coff) {
1497             aop->coff++;
1498             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1499         }
1500         while (offset < aop->coff) {
1501             aop->coff-- ;
1502             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1503         }
1504         aop->coff = offset;
1505         
1506         if (aop->paged) {
1507             MOVA(s);           
1508             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1509             
1510         } else
1511             if (*s == '@') {
1512                 MOVA(s);
1513                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1514             } else
1515                 if (strcmp(s,"r0") == 0 ||
1516                     strcmp(s,"r1") == 0 ||
1517                     strcmp(s,"r2") == 0 ||
1518                     strcmp(s,"r3") == 0 ||
1519                     strcmp(s,"r4") == 0 ||
1520                     strcmp(s,"r5") == 0 ||
1521                     strcmp(s,"r6") == 0 || 
1522                     strcmp(s,"r7") == 0 ) {
1523                     char buffer[10];
1524                     sprintf(buffer,"a%s",s);
1525                     pic14_emitcode("mov","@%s,%s",
1526                              aop->aopu.aop_ptr->name,buffer);
1527                 } else
1528                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1529         
1530         break;
1531         
1532     case AOP_STK:
1533         if (strcmp(s,"a") == 0)
1534             pic14_emitcode("push","acc");
1535         else
1536             pic14_emitcode("push","%s",s);
1537         
1538         break;
1539         
1540     case AOP_CRY:
1541         /* if bit variable */
1542         if (!aop->aopu.aop_dir) {
1543             pic14_emitcode("clr","a");
1544             pic14_emitcode("rlc","a");
1545         } else {
1546             if (s == zero) 
1547                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1548             else
1549                 if (s == one)
1550                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1551                 else
1552                     if (!strcmp(s,"c"))
1553                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1554                     else {
1555                         lbl = newiTempLabel(NULL);
1556                         
1557                         if (strcmp(s,"a")) {
1558                             MOVA(s);
1559                         }
1560                         pic14_emitcode("clr","c");
1561                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1562                         pic14_emitcode("cpl","c");
1563                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1564                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1565                     }
1566         }
1567         break;
1568         
1569     case AOP_STR:
1570         aop->coff = offset;
1571         if (strcmp(aop->aopu.aop_str[offset],s))
1572             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1573         break;
1574         
1575     case AOP_ACC:
1576         aop->coff = offset;
1577         if (!offset && (strcmp(s,"acc") == 0))
1578             break;
1579         
1580         if (strcmp(aop->aopu.aop_str[offset],s))
1581             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1582         break;
1583
1584     default :
1585         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1586                "aopPut got unsupported aop->type");
1587         exit(0);    
1588     }    
1589
1590 }
1591
1592 /*-----------------------------------------------------------------*/
1593 /* reAdjustPreg - points a register back to where it should        */
1594 /*-----------------------------------------------------------------*/
1595 static void reAdjustPreg (asmop *aop)
1596 {
1597     int size ;
1598
1599     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1600     aop->coff = 0;
1601     if ((size = aop->size) <= 1)
1602         return ;
1603     size-- ;
1604     switch (aop->type) {
1605         case AOP_R0 :
1606         case AOP_R1 :
1607             while (size--)
1608                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1609             break;          
1610         case AOP_DPTR :
1611         case AOP_DPTR2:
1612             if (aop->type == AOP_DPTR2)
1613             {
1614                 genSetDPTR(1);
1615             } 
1616             while (size--)
1617             {
1618                 pic14_emitcode("lcall","__decdptr");
1619             }
1620                 
1621             if (aop->type == AOP_DPTR2)
1622             {
1623                 genSetDPTR(0);
1624             }                
1625             break;  
1626
1627     }   
1628
1629 }
1630
1631 /*-----------------------------------------------------------------*/
1632 /* genNotFloat - generates not for float operations              */
1633 /*-----------------------------------------------------------------*/
1634 static void genNotFloat (operand *op, operand *res)
1635 {
1636     int size, offset;
1637     char *l;
1638     symbol *tlbl ;
1639
1640     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1641     /* we will put 127 in the first byte of 
1642     the result */
1643     aopPut(AOP(res),"#127",0);
1644     size = AOP_SIZE(op) - 1;
1645     offset = 1;
1646
1647     l = aopGet(op->aop,offset++,FALSE,FALSE);
1648     MOVA(l);    
1649
1650     while(size--) {
1651         pic14_emitcode("orl","a,%s",
1652                  aopGet(op->aop,
1653                         offset++,FALSE,FALSE));
1654     }
1655     tlbl = newiTempLabel(NULL);
1656
1657     tlbl = newiTempLabel(NULL);
1658     aopPut(res->aop,one,1);
1659     pic14_emitcode("jz","%05d_DS_",(tlbl->key+100));
1660     aopPut(res->aop,zero,1);
1661     pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
1662
1663     size = res->aop->size - 2;
1664     offset = 2;    
1665     /* put zeros in the rest */
1666     while (size--) 
1667         aopPut(res->aop,zero,offset++);
1668 }
1669
1670 #if 0
1671 /*-----------------------------------------------------------------*/
1672 /* opIsGptr: returns non-zero if the passed operand is             */   
1673 /* a generic pointer type.                                         */
1674 /*-----------------------------------------------------------------*/ 
1675 static int opIsGptr(operand *op)
1676 {
1677     sym_link *type = operandType(op);
1678     
1679     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1680     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1681     {
1682         return 1;
1683     }
1684     return 0;        
1685 }
1686 #endif
1687
1688 /*-----------------------------------------------------------------*/
1689 /* pic14_getDataSize - get the operand data size                         */
1690 /*-----------------------------------------------------------------*/
1691 int pic14_getDataSize(operand *op)
1692 {
1693     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1694
1695
1696     return AOP_SIZE(op);
1697
1698     // tsd- in the pic port, the genptr size is 1, so this code here
1699     // fails. ( in the 8051 port, the size was 4).
1700 #if 0
1701     int size;
1702     size = AOP_SIZE(op);
1703     if (size == GPTRSIZE)
1704     {
1705         sym_link *type = operandType(op);
1706         if (IS_GENPTR(type))
1707         {
1708             /* generic pointer; arithmetic operations
1709              * should ignore the high byte (pointer type).
1710              */
1711             size--;
1712     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1713         }
1714     }
1715     return size;
1716 #endif
1717 }
1718
1719 /*-----------------------------------------------------------------*/
1720 /* pic14_outAcc - output Acc                                             */
1721 /*-----------------------------------------------------------------*/
1722 void pic14_outAcc(operand *result)
1723 {
1724   int size,offset;
1725   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1726   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1727
1728
1729   size = pic14_getDataSize(result);
1730   if(size){
1731     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1732     size--;
1733     offset = 1;
1734     /* unsigned or positive */
1735     while(size--)
1736       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1737   }
1738
1739 }
1740
1741 /*-----------------------------------------------------------------*/
1742 /* pic14_outBitC - output a bit C                                        */
1743 /*-----------------------------------------------------------------*/
1744 void pic14_outBitC(operand *result)
1745 {
1746
1747     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1748     /* if the result is bit */
1749     if (AOP_TYPE(result) == AOP_CRY) 
1750         aopPut(AOP(result),"c",0);
1751     else {
1752         pic14_emitcode("clr","a  ; %d", __LINE__);
1753         pic14_emitcode("rlc","a");
1754         pic14_outAcc(result);
1755     }
1756 }
1757
1758 /*-----------------------------------------------------------------*/
1759 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1760 /*-----------------------------------------------------------------*/
1761 void pic14_toBoolean(operand *oper)
1762 {
1763     int size = AOP_SIZE(oper) - 1;
1764     int offset = 1;
1765
1766     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1767
1768     if ( AOP_TYPE(oper) != AOP_ACC) {
1769       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1770     }
1771     while (size--) {
1772       emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1773     }
1774 }
1775
1776
1777 /*-----------------------------------------------------------------*/
1778 /* genNot - generate code for ! operation                          */
1779 /*-----------------------------------------------------------------*/
1780 static void genNot (iCode *ic)
1781 {
1782   symbol *tlbl;
1783   sym_link *optype = operandType(IC_LEFT(ic));
1784   int size;
1785
1786   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1787   /* assign asmOps to operand & result */
1788   aopOp (IC_LEFT(ic),ic,FALSE);
1789   aopOp (IC_RESULT(ic),ic,TRUE);
1790
1791   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1792   /* if in bit space then a special case */
1793   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1794     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1795       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1796       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1797     } else {
1798       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1799       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1800       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1801     }
1802     goto release;
1803   }
1804
1805   /* if type float then do float */
1806   if (IS_FLOAT(optype)) {
1807     genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1808     goto release;
1809   }
1810
1811   size = AOP_SIZE(IC_RESULT(ic));
1812   if(size == 1) {
1813     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1814     emitpcode(POC_ANDLW,popGetLit(1));
1815     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1816     goto release;
1817   }
1818   pic14_toBoolean(IC_LEFT(ic));
1819
1820   tlbl = newiTempLabel(NULL);
1821   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1822   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1823   pic14_outBitC(IC_RESULT(ic));
1824
1825  release:    
1826   /* release the aops */
1827   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1828   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1829 }
1830
1831
1832 /*-----------------------------------------------------------------*/
1833 /* genCpl - generate code for complement                           */
1834 /*-----------------------------------------------------------------*/
1835 static void genCpl (iCode *ic)
1836 {
1837     int offset = 0;
1838     int size ;
1839
1840
1841     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1842     /* assign asmOps to operand & result */
1843     aopOp (IC_LEFT(ic),ic,FALSE);
1844     aopOp (IC_RESULT(ic),ic,TRUE);
1845
1846     /* if both are in bit space then 
1847     a special case */
1848     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1849         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1850
1851         pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1852         pic14_emitcode("cpl","c"); 
1853         pic14_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1854         goto release; 
1855     } 
1856
1857     size = AOP_SIZE(IC_RESULT(ic));
1858     while (size--) {
1859         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1860         MOVA(l);       
1861         pic14_emitcode("cpl","a");
1862         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1863     }
1864
1865
1866 release:
1867     /* release the aops */
1868     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1869     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1870 }
1871
1872 /*-----------------------------------------------------------------*/
1873 /* genUminusFloat - unary minus for floating points                */
1874 /*-----------------------------------------------------------------*/
1875 static void genUminusFloat(operand *op,operand *result)
1876 {
1877     int size ,offset =0 ;
1878     char *l;
1879
1880     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1881     /* for this we just need to flip the 
1882     first it then copy the rest in place */
1883     size = AOP_SIZE(op) - 1;
1884     l = aopGet(AOP(op),3,FALSE,FALSE);
1885
1886     MOVA(l);    
1887
1888     pic14_emitcode("cpl","acc.7");
1889     aopPut(AOP(result),"a",3);    
1890
1891     while(size--) {
1892         aopPut(AOP(result),
1893                aopGet(AOP(op),offset,FALSE,FALSE),
1894                offset);
1895         offset++;
1896     }          
1897 }
1898
1899 /*-----------------------------------------------------------------*/
1900 /* genUminus - unary minus code generation                         */
1901 /*-----------------------------------------------------------------*/
1902 static void genUminus (iCode *ic)
1903 {
1904   int size, i;
1905   sym_link *optype, *rtype;
1906
1907
1908   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1909   /* assign asmops */
1910   aopOp(IC_LEFT(ic),ic,FALSE);
1911   aopOp(IC_RESULT(ic),ic,TRUE);
1912
1913   /* if both in bit space then special
1914      case */
1915   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1916       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1917
1918     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1919     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1920     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1921
1922     goto release; 
1923   } 
1924
1925   optype = operandType(IC_LEFT(ic));
1926   rtype = operandType(IC_RESULT(ic));
1927
1928   /* if float then do float stuff */
1929   if (IS_FLOAT(optype)) {
1930     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1931     goto release;
1932   }
1933
1934   /* otherwise subtract from zero by taking the 2's complement */
1935   size = AOP_SIZE(IC_LEFT(ic));
1936
1937   for(i=0; i<size; i++) {
1938     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1939       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1940     else {
1941       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1942       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1943     }
1944   }
1945
1946   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1947   for(i=1; i<size; i++) {
1948     emitSKPNZ;
1949     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1950   }
1951
1952  release:
1953   /* release the aops */
1954   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1955   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1956 }
1957
1958 /*-----------------------------------------------------------------*/
1959 /* saveRegisters - will look for a call and save the registers     */
1960 /*-----------------------------------------------------------------*/
1961 static void saveRegisters(iCode *lic) 
1962 {
1963     int i;
1964     iCode *ic;
1965     bitVect *rsave;
1966     sym_link *dtype;
1967
1968     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1969     /* look for call */
1970     for (ic = lic ; ic ; ic = ic->next) 
1971         if (ic->op == CALL || ic->op == PCALL)
1972             break;
1973
1974     if (!ic) {
1975         fprintf(stderr,"found parameter push with no function call\n");
1976         return ;
1977     }
1978
1979     /* if the registers have been saved already then
1980     do nothing */
1981     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1982         return ;
1983
1984     /* find the registers in use at this time 
1985     and push them away to safety */
1986     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1987                           ic->rUsed);
1988
1989     ic->regsSaved = 1;
1990     if (options.useXstack) {
1991         if (bitVectBitValue(rsave,R0_IDX))
1992             pic14_emitcode("mov","b,r0");
1993         pic14_emitcode("mov","r0,%s",spname);
1994         for (i = 0 ; i < pic14_nRegs ; i++) {
1995             if (bitVectBitValue(rsave,i)) {
1996                 if (i == R0_IDX)
1997                     pic14_emitcode("mov","a,b");
1998                 else
1999                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2000                 pic14_emitcode("movx","@r0,a");
2001                 pic14_emitcode("inc","r0");
2002             }
2003         }
2004         pic14_emitcode("mov","%s,r0",spname);
2005         if (bitVectBitValue(rsave,R0_IDX))
2006             pic14_emitcode("mov","r0,b");           
2007     }// else
2008     //for (i = 0 ; i < pic14_nRegs ; i++) {
2009     //    if (bitVectBitValue(rsave,i))
2010     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2011     //}
2012
2013     dtype = operandType(IC_LEFT(ic));
2014     if (currFunc && dtype && 
2015         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2016         IFFUNC_ISISR(currFunc->type) &&
2017         !ic->bankSaved) 
2018
2019         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2020
2021 }
2022 /*-----------------------------------------------------------------*/
2023 /* unsaveRegisters - pop the pushed registers                      */
2024 /*-----------------------------------------------------------------*/
2025 static void unsaveRegisters (iCode *ic)
2026 {
2027     int i;
2028     bitVect *rsave;
2029
2030     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2031     /* find the registers in use at this time 
2032     and push them away to safety */
2033     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2034                           ic->rUsed);
2035     
2036     if (options.useXstack) {
2037         pic14_emitcode("mov","r0,%s",spname);   
2038         for (i =  pic14_nRegs ; i >= 0 ; i--) {
2039             if (bitVectBitValue(rsave,i)) {
2040                 pic14_emitcode("dec","r0");
2041                 pic14_emitcode("movx","a,@r0");
2042                 if (i == R0_IDX)
2043                     pic14_emitcode("mov","b,a");
2044                 else
2045                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2046             }       
2047
2048         }
2049         pic14_emitcode("mov","%s,r0",spname);
2050         if (bitVectBitValue(rsave,R0_IDX))
2051             pic14_emitcode("mov","r0,b");
2052     } //else
2053     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2054     //    if (bitVectBitValue(rsave,i))
2055     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2056     //}
2057
2058 }  
2059
2060
2061 /*-----------------------------------------------------------------*/
2062 /* pushSide -                                                      */
2063 /*-----------------------------------------------------------------*/
2064 static void pushSide(operand * oper, int size)
2065 {
2066 #if 0
2067         int offset = 0;
2068     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2069         while (size--) {
2070                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2071                 if (AOP_TYPE(oper) != AOP_REG &&
2072                     AOP_TYPE(oper) != AOP_DIR &&
2073                     strcmp(l,"a") ) {
2074                         pic14_emitcode("mov","a,%s",l);
2075                         pic14_emitcode("push","acc");
2076                 } else
2077                         pic14_emitcode("push","%s",l);
2078         }
2079 #endif
2080 }
2081
2082 /*-----------------------------------------------------------------*/
2083 /* assignResultValue -                                             */
2084 /*-----------------------------------------------------------------*/
2085 static void assignResultValue(operand * oper)
2086 {
2087   int size = AOP_SIZE(oper);
2088
2089   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2090
2091   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2092
2093   if(!GpsuedoStkPtr) {
2094     /* The last byte in the assignment is in W */
2095     size--;
2096     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2097     GpsuedoStkPtr++;
2098   }
2099
2100   while (size--) {
2101     emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
2102     GpsuedoStkPtr++;
2103     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2104   }
2105 }
2106
2107
2108 /*-----------------------------------------------------------------*/
2109 /* genIpush - genrate code for pushing this gets a little complex  */
2110 /*-----------------------------------------------------------------*/
2111 static void genIpush (iCode *ic)
2112 {
2113
2114   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2115 #if 0
2116     int size, offset = 0 ;
2117     char *l;
2118
2119
2120     /* if this is not a parm push : ie. it is spill push 
2121     and spill push is always done on the local stack */
2122     if (!ic->parmPush) {
2123
2124         /* and the item is spilt then do nothing */
2125         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2126             return ;
2127
2128         aopOp(IC_LEFT(ic),ic,FALSE);
2129         size = AOP_SIZE(IC_LEFT(ic));
2130         /* push it on the stack */
2131         while(size--) {
2132             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2133             if (*l == '#') {
2134                 MOVA(l);
2135                 l = "acc";
2136             }
2137             pic14_emitcode("push","%s",l);
2138         }
2139         return ;        
2140     }
2141
2142     /* this is a paramter push: in this case we call
2143     the routine to find the call and save those
2144     registers that need to be saved */   
2145     saveRegisters(ic);
2146
2147     /* then do the push */
2148     aopOp(IC_LEFT(ic),ic,FALSE);
2149
2150
2151         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2152     size = AOP_SIZE(IC_LEFT(ic));
2153
2154     while (size--) {
2155         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2156         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2157             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2158             strcmp(l,"a") ) {
2159             pic14_emitcode("mov","a,%s",l);
2160             pic14_emitcode("push","acc");
2161         } else
2162             pic14_emitcode("push","%s",l);
2163     }       
2164
2165     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2166 #endif
2167 }
2168
2169 /*-----------------------------------------------------------------*/
2170 /* genIpop - recover the registers: can happen only for spilling   */
2171 /*-----------------------------------------------------------------*/
2172 static void genIpop (iCode *ic)
2173 {
2174   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2175 #if 0
2176     int size,offset ;
2177
2178
2179     /* if the temp was not pushed then */
2180     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2181         return ;
2182
2183     aopOp(IC_LEFT(ic),ic,FALSE);
2184     size = AOP_SIZE(IC_LEFT(ic));
2185     offset = (size-1);
2186     while (size--) 
2187         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2188                                    FALSE,TRUE));
2189
2190     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2191 #endif
2192 }
2193
2194 /*-----------------------------------------------------------------*/
2195 /* unsaverbank - restores the resgister bank from stack            */
2196 /*-----------------------------------------------------------------*/
2197 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2198 {
2199   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2200 #if 0
2201     int i;
2202     asmop *aop ;
2203     regs *r = NULL;
2204
2205     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2206     if (popPsw) {
2207         if (options.useXstack) {
2208             aop = newAsmop(0);
2209             r = getFreePtr(ic,&aop,FALSE);
2210             
2211             
2212             pic14_emitcode("mov","%s,_spx",r->name);
2213             pic14_emitcode("movx","a,@%s",r->name);
2214             pic14_emitcode("mov","psw,a");
2215             pic14_emitcode("dec","%s",r->name);
2216             
2217         }else
2218             pic14_emitcode ("pop","psw");
2219     }
2220
2221     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2222         if (options.useXstack) {       
2223             pic14_emitcode("movx","a,@%s",r->name);
2224             //pic14_emitcode("mov","(%s+%d),a",
2225             //       regspic14[i].base,8*bank+regspic14[i].offset);
2226             pic14_emitcode("dec","%s",r->name);
2227
2228         } else 
2229           pic14_emitcode("pop",""); //"(%s+%d)",
2230         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2231     }
2232
2233     if (options.useXstack) {
2234
2235         pic14_emitcode("mov","_spx,%s",r->name);
2236         freeAsmop(NULL,aop,ic,TRUE);
2237
2238     }
2239 #endif 
2240 }
2241
2242 /*-----------------------------------------------------------------*/
2243 /* saverbank - saves an entire register bank on the stack          */
2244 /*-----------------------------------------------------------------*/
2245 static void saverbank (int bank, iCode *ic, bool pushPsw)
2246 {
2247   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2248 #if 0
2249     int i;
2250     asmop *aop ;
2251     regs *r = NULL;
2252
2253     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2254     if (options.useXstack) {
2255
2256         aop = newAsmop(0);
2257         r = getFreePtr(ic,&aop,FALSE);  
2258         pic14_emitcode("mov","%s,_spx",r->name);
2259
2260     }
2261
2262     for (i = 0 ; i < pic14_nRegs ;i++) {
2263         if (options.useXstack) {
2264             pic14_emitcode("inc","%s",r->name);
2265             //pic14_emitcode("mov","a,(%s+%d)",
2266             //         regspic14[i].base,8*bank+regspic14[i].offset);
2267             pic14_emitcode("movx","@%s,a",r->name);           
2268         } else 
2269           pic14_emitcode("push","");// "(%s+%d)",
2270                      //regspic14[i].base,8*bank+regspic14[i].offset);
2271     }
2272     
2273     if (pushPsw) {
2274         if (options.useXstack) {
2275             pic14_emitcode("mov","a,psw");
2276             pic14_emitcode("movx","@%s,a",r->name);     
2277             pic14_emitcode("inc","%s",r->name);
2278             pic14_emitcode("mov","_spx,%s",r->name);       
2279             freeAsmop (NULL,aop,ic,TRUE);
2280             
2281         } else
2282             pic14_emitcode("push","psw");
2283         
2284         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2285     }
2286     ic->bankSaved = 1;
2287 #endif
2288 }
2289
2290 /*-----------------------------------------------------------------*/
2291 /* genCall - generates a call statement                            */
2292 /*-----------------------------------------------------------------*/
2293 static void genCall (iCode *ic)
2294 {
2295   sym_link *dtype;   
2296
2297   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2298
2299   /* if caller saves & we have not saved then */
2300   if (!ic->regsSaved)
2301     saveRegisters(ic);
2302
2303   /* if we are calling a function that is not using
2304      the same register bank then we need to save the
2305      destination registers on the stack */
2306   dtype = operandType(IC_LEFT(ic));
2307   if (currFunc && dtype && 
2308       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2309       IFFUNC_ISISR(currFunc->type) &&
2310       !ic->bankSaved) 
2311
2312     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2313
2314   /* if send set is not empty the assign */
2315   if (_G.sendSet) {
2316     iCode *sic;
2317     /* For the Pic port, there is no data stack.
2318      * So parameters passed to functions are stored
2319      * in registers. (The pCode optimizer will get
2320      * rid of most of these :).
2321      */
2322     int psuedoStkPtr=-1; 
2323     int firstTimeThruLoop = 1;
2324
2325     _G.sendSet = reverseSet(_G.sendSet);
2326
2327     /* First figure how many parameters are getting passed */
2328     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2329          sic = setNextItem(_G.sendSet)) {
2330
2331       aopOp(IC_LEFT(sic),sic,FALSE);
2332       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2333       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2334     }
2335
2336     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2337          sic = setNextItem(_G.sendSet)) {
2338       int size, offset = 0;
2339
2340       aopOp(IC_LEFT(sic),sic,FALSE);
2341       size = AOP_SIZE(IC_LEFT(sic));
2342
2343
2344       while (size--) {
2345         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2346                              AopType(AOP_TYPE(IC_LEFT(sic))));
2347
2348         if(!firstTimeThruLoop) {
2349           /* If this is not the first time we've been through the loop
2350            * then we need to save the parameter in a temporary
2351            * register. The last byte of the last parameter is
2352            * passed in W. */
2353           emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr));
2354
2355         }
2356         firstTimeThruLoop=0;
2357
2358         //if (strcmp(l,fReturn[offset])) {
2359
2360         if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
2361              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2362           emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset));
2363         else
2364           emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset));
2365
2366         //}
2367         offset++;
2368       }
2369       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2370     }
2371     _G.sendSet = NULL;
2372   }
2373   /* make the call */
2374   emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2375                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2376                                       OP_SYMBOL(IC_LEFT(ic))->name));
2377
2378   GpsuedoStkPtr=0;
2379   /* if we need assign a result value */
2380   if ((IS_ITEMP(IC_RESULT(ic)) && 
2381        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2382         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2383       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2384
2385     _G.accInUse++;
2386     aopOp(IC_RESULT(ic),ic,FALSE);
2387     _G.accInUse--;
2388
2389     assignResultValue(IC_RESULT(ic));
2390
2391     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2392                          AopType(AOP_TYPE(IC_RESULT(ic))));
2393                 
2394     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2395   }
2396
2397   /* adjust the stack for parameters if 
2398      required */
2399   if (ic->parmBytes) {
2400     int i;
2401     if (ic->parmBytes > 3) {
2402       pic14_emitcode("mov","a,%s",spname);
2403       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2404       pic14_emitcode("mov","%s,a",spname);
2405     } else 
2406       for ( i = 0 ; i <  ic->parmBytes ;i++)
2407         pic14_emitcode("dec","%s",spname);
2408
2409   }
2410
2411   /* if register bank was saved then pop them */
2412   if (ic->bankSaved)
2413     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2414
2415   /* if we hade saved some registers then unsave them */
2416   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2417     unsaveRegisters (ic);
2418
2419
2420 }
2421
2422 /*-----------------------------------------------------------------*/
2423 /* genPcall - generates a call by pointer statement                */
2424 /*-----------------------------------------------------------------*/
2425 static void genPcall (iCode *ic)
2426 {
2427     sym_link *dtype;
2428     symbol *rlbl = newiTempLabel(NULL);
2429
2430
2431     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2432     /* if caller saves & we have not saved then */
2433     if (!ic->regsSaved)
2434         saveRegisters(ic);
2435
2436     /* if we are calling a function that is not using
2437     the same register bank then we need to save the
2438     destination registers on the stack */
2439     dtype = operandType(IC_LEFT(ic));
2440     if (currFunc && dtype && 
2441         IFFUNC_ISISR(currFunc->type) &&
2442         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2443         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2444
2445
2446     /* push the return address on to the stack */
2447     pic14_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2448     pic14_emitcode("push","acc");    
2449     pic14_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2450     pic14_emitcode("push","acc");
2451     
2452     if (options.model == MODEL_FLAT24)
2453     {
2454         pic14_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2455         pic14_emitcode("push","acc");    
2456     }
2457
2458     /* now push the calling address */
2459     aopOp(IC_LEFT(ic),ic,FALSE);
2460
2461     pushSide(IC_LEFT(ic), FPTRSIZE);
2462
2463     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2464
2465     /* if send set is not empty the assign */
2466     if (_G.sendSet) {
2467         iCode *sic ;
2468
2469         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2470              sic = setNextItem(_G.sendSet)) {
2471             int size, offset = 0;
2472             aopOp(IC_LEFT(sic),sic,FALSE);
2473             size = AOP_SIZE(IC_LEFT(sic));
2474             while (size--) {
2475                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2476                                 FALSE,FALSE);
2477                 if (strcmp(l,fReturn[offset]))
2478                     pic14_emitcode("mov","%s,%s",
2479                              fReturn[offset],
2480                              l);
2481                 offset++;
2482             }
2483             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2484         }
2485         _G.sendSet = NULL;
2486     }
2487
2488     pic14_emitcode("ret","");
2489     pic14_emitcode("","%05d_DS_:",(rlbl->key+100));
2490
2491
2492     /* if we need assign a result value */
2493     if ((IS_ITEMP(IC_RESULT(ic)) &&
2494          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2495           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2496         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2497
2498         _G.accInUse++;
2499         aopOp(IC_RESULT(ic),ic,FALSE);
2500         _G.accInUse--;
2501         
2502         assignResultValue(IC_RESULT(ic));
2503
2504         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2505     }
2506
2507     /* adjust the stack for parameters if 
2508     required */
2509     if (ic->parmBytes) {
2510         int i;
2511         if (ic->parmBytes > 3) {
2512             pic14_emitcode("mov","a,%s",spname);
2513             pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2514             pic14_emitcode("mov","%s,a",spname);
2515         } else 
2516             for ( i = 0 ; i <  ic->parmBytes ;i++)
2517                 pic14_emitcode("dec","%s",spname);
2518
2519     }
2520
2521     /* if register bank was saved then unsave them */
2522     if (currFunc && dtype && 
2523         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2524         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2525
2526     /* if we hade saved some registers then
2527     unsave them */
2528     if (ic->regsSaved)
2529         unsaveRegisters (ic);
2530
2531 }
2532
2533 /*-----------------------------------------------------------------*/
2534 /* resultRemat - result  is rematerializable                       */
2535 /*-----------------------------------------------------------------*/
2536 static int resultRemat (iCode *ic)
2537 {
2538     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2539     if (SKIP_IC(ic) || ic->op == IFX)
2540         return 0;
2541
2542     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2543         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2544         if (sym->remat && !POINTER_SET(ic)) 
2545             return 1;
2546     }
2547
2548     return 0;
2549 }
2550
2551 #if defined(__BORLANDC__) || defined(_MSC_VER)
2552 #define STRCASECMP stricmp
2553 #else
2554 #define STRCASECMP strcasecmp
2555 #endif
2556
2557 #if 0
2558 /*-----------------------------------------------------------------*/
2559 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2560 /*-----------------------------------------------------------------*/
2561 static bool inExcludeList(char *s)
2562 {
2563   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2564     int i =0;
2565     
2566     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2567     if (options.excludeRegs[i] &&
2568     STRCASECMP(options.excludeRegs[i],"none") == 0)
2569         return FALSE ;
2570
2571     for ( i = 0 ; options.excludeRegs[i]; i++) {
2572         if (options.excludeRegs[i] &&
2573         STRCASECMP(s,options.excludeRegs[i]) == 0)
2574             return TRUE;
2575     }
2576     return FALSE ;
2577 }
2578 #endif
2579
2580 /*-----------------------------------------------------------------*/
2581 /* genFunction - generated code for function entry                 */
2582 /*-----------------------------------------------------------------*/
2583 static void genFunction (iCode *ic)
2584 {
2585     symbol *sym;
2586     sym_link *ftype;
2587
2588     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2589
2590     labelOffset += (max_key+4);
2591     max_key=0;
2592     GpsuedoStkPtr=0;
2593     _G.nRegsSaved = 0;
2594     /* create the function header */
2595     pic14_emitcode(";","-----------------------------------------");
2596     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2597     pic14_emitcode(";","-----------------------------------------");
2598
2599     pic14_emitcode("","%s:",sym->rname);
2600     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2601
2602     ftype = operandType(IC_LEFT(ic));
2603
2604     /* if critical function then turn interrupts off */
2605     if (IFFUNC_ISCRITICAL(ftype))
2606         pic14_emitcode("clr","ea");
2607
2608     /* here we need to generate the equates for the
2609        register bank if required */
2610 #if 0
2611     if (FUNC_REGBANK(ftype) != rbank) {
2612         int i ;
2613
2614         rbank = FUNC_REGBANK(ftype);
2615         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2616             if (strcmp(regspic14[i].base,"0") == 0)
2617                 pic14_emitcode("","%s = 0x%02x",
2618                          regspic14[i].dname,
2619                          8*rbank+regspic14[i].offset);
2620             else
2621                 pic14_emitcode ("","%s = %s + 0x%02x",
2622                           regspic14[i].dname,
2623                           regspic14[i].base,
2624                           8*rbank+regspic14[i].offset);
2625         }
2626     }
2627 #endif
2628
2629     /* if this is an interrupt service routine then
2630     save acc, b, dpl, dph  */
2631     if (IFFUNC_ISISR(sym->type)) {
2632       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2633       emitpcodeNULLop(POC_NOP);
2634       emitpcodeNULLop(POC_NOP);
2635       emitpcodeNULLop(POC_NOP);
2636       emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2637       emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2638       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2639       emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2640
2641       pBlockConvert2ISR(pb);
2642 #if 0  
2643         if (!inExcludeList("acc"))          
2644             pic14_emitcode ("push","acc");      
2645         if (!inExcludeList("b"))
2646             pic14_emitcode ("push","b");
2647         if (!inExcludeList("dpl"))
2648             pic14_emitcode ("push","dpl");
2649         if (!inExcludeList("dph"))
2650             pic14_emitcode ("push","dph");
2651         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2652         {
2653             pic14_emitcode ("push", "dpx");
2654             /* Make sure we're using standard DPTR */
2655             pic14_emitcode ("push", "dps");
2656             pic14_emitcode ("mov", "dps, #0x00");
2657             if (options.stack10bit)
2658             {   
2659                 /* This ISR could conceivably use DPTR2. Better save it. */
2660                 pic14_emitcode ("push", "dpl1");
2661                 pic14_emitcode ("push", "dph1");
2662                 pic14_emitcode ("push", "dpx1");
2663             }
2664         }
2665         /* if this isr has no bank i.e. is going to
2666            run with bank 0 , then we need to save more
2667            registers :-) */
2668         if (!FUNC_REGBANK(sym->type)) {
2669
2670             /* if this function does not call any other
2671                function then we can be economical and
2672                save only those registers that are used */
2673             if (! IFFUNC_HASFCALL(sym->type)) {
2674                 int i;
2675
2676                 /* if any registers used */
2677                 if (sym->regsUsed) {
2678                     /* save the registers used */
2679                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2680                         if (bitVectBitValue(sym->regsUsed,i) ||
2681                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2682                           pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);                         
2683                     }
2684                 }
2685                 
2686             } else {
2687                 /* this function has  a function call cannot
2688                    determines register usage so we will have the
2689                    entire bank */
2690                 saverbank(0,ic,FALSE);
2691             }       
2692         }
2693 #endif
2694     } else {
2695         /* if callee-save to be used for this function
2696            then save the registers being used in this function */
2697         if (IFFUNC_CALLEESAVES(sym->type)) {
2698             int i;
2699             
2700             /* if any registers used */
2701             if (sym->regsUsed) {
2702                 /* save the registers used */
2703                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2704                     if (bitVectBitValue(sym->regsUsed,i) ||
2705                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2706                       //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2707                         _G.nRegsSaved++;
2708                     }
2709                 }
2710             }
2711         }
2712     }
2713
2714     /* set the register bank to the desired value */
2715     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2716         pic14_emitcode("push","psw");
2717         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2718     }
2719
2720     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2721
2722         if (options.useXstack) {
2723             pic14_emitcode("mov","r0,%s",spname);
2724             pic14_emitcode("mov","a,_bp");
2725             pic14_emitcode("movx","@r0,a");
2726             pic14_emitcode("inc","%s",spname);
2727         }
2728         else
2729         {
2730             /* set up the stack */
2731             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2732         }
2733         pic14_emitcode ("mov","_bp,%s",spname);
2734     }
2735
2736     /* adjust the stack for the function */
2737     if (sym->stack) {
2738
2739         int i = sym->stack;
2740         if (i > 256 ) 
2741             werror(W_STACK_OVERFLOW,sym->name);
2742
2743         if (i > 3 && sym->recvSize < 4) {              
2744
2745             pic14_emitcode ("mov","a,sp");
2746             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2747             pic14_emitcode ("mov","sp,a");
2748            
2749         }
2750         else
2751             while(i--)
2752                 pic14_emitcode("inc","sp");
2753     }
2754
2755      if (sym->xstack) {
2756
2757         pic14_emitcode ("mov","a,_spx");
2758         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2759         pic14_emitcode ("mov","_spx,a");
2760     }    
2761
2762 }
2763
2764 /*-----------------------------------------------------------------*/
2765 /* genEndFunction - generates epilogue for functions               */
2766 /*-----------------------------------------------------------------*/
2767 static void genEndFunction (iCode *ic)
2768 {
2769     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2770
2771     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2772
2773     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2774     {
2775         pic14_emitcode ("mov","%s,_bp",spname);
2776     }
2777
2778     /* if use external stack but some variables were
2779     added to the local stack then decrement the
2780     local stack */
2781     if (options.useXstack && sym->stack) {      
2782         pic14_emitcode("mov","a,sp");
2783         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2784         pic14_emitcode("mov","sp,a");
2785     }
2786
2787
2788     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2789         if (options.useXstack) {
2790             pic14_emitcode("mov","r0,%s",spname);
2791             pic14_emitcode("movx","a,@r0");
2792             pic14_emitcode("mov","_bp,a");
2793             pic14_emitcode("dec","%s",spname);
2794         }
2795         else
2796         {
2797             pic14_emitcode ("pop","_bp");
2798         }
2799     }
2800
2801     /* restore the register bank  */    
2802     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2803         pic14_emitcode ("pop","psw");
2804
2805     if (IFFUNC_ISISR(sym->type)) {
2806
2807         /* now we need to restore the registers */
2808         /* if this isr has no bank i.e. is going to
2809            run with bank 0 , then we need to save more
2810            registers :-) */
2811         if (!FUNC_REGBANK(sym->type)) {
2812             
2813             /* if this function does not call any other
2814                function then we can be economical and
2815                save only those registers that are used */
2816             if (! IFFUNC_HASFCALL(sym->type)) {
2817                 int i;
2818                 
2819                 /* if any registers used */
2820                 if (sym->regsUsed) {
2821                     /* save the registers used */
2822                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2823                         if (bitVectBitValue(sym->regsUsed,i) ||
2824                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2825                           pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2826                     }
2827                 }
2828                 
2829             } else {
2830                 /* this function has  a function call cannot
2831                    determines register usage so we will have the
2832                    entire bank */
2833                 unsaverbank(0,ic,FALSE);
2834             }       
2835         }
2836 #if 0
2837         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2838         {
2839             if (options.stack10bit)
2840             {
2841                 pic14_emitcode ("pop", "dpx1");
2842                 pic14_emitcode ("pop", "dph1");
2843                 pic14_emitcode ("pop", "dpl1");
2844             }   
2845             pic14_emitcode ("pop", "dps");
2846             pic14_emitcode ("pop", "dpx");
2847         }
2848         if (!inExcludeList("dph"))
2849             pic14_emitcode ("pop","dph");
2850         if (!inExcludeList("dpl"))
2851             pic14_emitcode ("pop","dpl");
2852         if (!inExcludeList("b"))
2853             pic14_emitcode ("pop","b");
2854         if (!inExcludeList("acc"))
2855             pic14_emitcode ("pop","acc");
2856
2857         if (IFFUNC_ISCRITICAL(sym->type))
2858             pic14_emitcode("setb","ea");
2859 #endif
2860
2861         /* if debug then send end of function */
2862 /*      if (options.debug && currFunc) { */
2863         if (currFunc) {
2864             _G.debugLine = 1;
2865             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2866                      FileBaseName(ic->filename),currFunc->lastLine,
2867                      ic->level,ic->block); 
2868             if (IS_STATIC(currFunc->etype))         
2869                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2870             else
2871                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2872             _G.debugLine = 0;
2873         }
2874         
2875         pic14_emitcode ("reti","");
2876
2877         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2878         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2879         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2880         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2881         emitpcode(POC_MOVFW,  popCopyReg(&pc_wsave));
2882         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2883
2884         emitpcodeNULLop(POC_RETFIE);
2885
2886     }
2887     else {
2888         if (IFFUNC_ISCRITICAL(sym->type))
2889             pic14_emitcode("setb","ea");
2890         
2891         if (IFFUNC_CALLEESAVES(sym->type)) {
2892             int i;
2893             
2894             /* if any registers used */
2895             if (sym->regsUsed) {
2896                 /* save the registers used */
2897                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2898                     if (bitVectBitValue(sym->regsUsed,i) ||
2899                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2900                       pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2901                 }
2902             }
2903             
2904         }
2905
2906         /* if debug then send end of function */
2907         if (currFunc) {
2908             _G.debugLine = 1;
2909             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2910                      FileBaseName(ic->filename),currFunc->lastLine,
2911                      ic->level,ic->block); 
2912             if (IS_STATIC(currFunc->etype))         
2913                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2914             else
2915                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2916             _G.debugLine = 0;
2917         }
2918
2919         pic14_emitcode ("return","");
2920         emitpcodeNULLop(POC_RETURN);
2921
2922         /* Mark the end of a function */
2923         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2924     }
2925
2926 }
2927
2928 /*-----------------------------------------------------------------*/
2929 /* genRet - generate code for return statement                     */
2930 /*-----------------------------------------------------------------*/
2931 static void genRet (iCode *ic)
2932 {
2933   int size,offset = 0 , pushed = 0;
2934     
2935   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2936   /* if we have no return value then
2937      just generate the "ret" */
2938   if (!IC_LEFT(ic)) 
2939     goto jumpret;       
2940     
2941   /* we have something to return then
2942      move the return value into place */
2943   aopOp(IC_LEFT(ic),ic,FALSE);
2944   size = AOP_SIZE(IC_LEFT(ic));
2945     
2946   while (size--) {
2947     char *l ;
2948     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2949       /* #NOCHANGE */
2950       l = aopGet(AOP(IC_LEFT(ic)),offset++,
2951                  FALSE,TRUE);
2952       pic14_emitcode("push","%s",l);
2953       pushed++;
2954     } else {
2955       l = aopGet(AOP(IC_LEFT(ic)),offset,
2956                  FALSE,FALSE);
2957       if (strcmp(fReturn[offset],l)) {
2958         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2959             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2960           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2961         }else {
2962           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2963         }
2964         if(size) {
2965           emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
2966           pic14_emitcode("movwf","%s",fReturn[offset]);
2967         }
2968         offset++;
2969       }
2970     }
2971   }    
2972
2973   if (pushed) {
2974     while(pushed) {
2975       pushed--;
2976       if (strcmp(fReturn[pushed],"a"))
2977         pic14_emitcode("pop",fReturn[pushed]);
2978       else
2979         pic14_emitcode("pop","acc");
2980     }
2981   }
2982   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2983     
2984  jumpret:
2985   /* generate a jump to the return label
2986      if the next is not the return statement */
2987   if (!(ic->next && ic->next->op == LABEL &&
2988         IC_LABEL(ic->next) == returnLabel)) {
2989         
2990     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2991     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2992   }
2993     
2994 }
2995
2996 /*-----------------------------------------------------------------*/
2997 /* genLabel - generates a label                                    */
2998 /*-----------------------------------------------------------------*/
2999 static void genLabel (iCode *ic)
3000 {
3001     /* special case never generate */
3002     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3003     if (IC_LABEL(ic) == entryLabel)
3004         return ;
3005
3006     emitpLabel(IC_LABEL(ic)->key);
3007     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3008 }
3009
3010 /*-----------------------------------------------------------------*/
3011 /* genGoto - generates a goto                                      */
3012 /*-----------------------------------------------------------------*/
3013 //tsd
3014 static void genGoto (iCode *ic)
3015 {
3016   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3017   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3018 }
3019
3020
3021 /*-----------------------------------------------------------------*/
3022 /* genMultbits :- multiplication of bits                           */
3023 /*-----------------------------------------------------------------*/
3024 static void genMultbits (operand *left, 
3025                          operand *right, 
3026                          operand *result)
3027 {
3028   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3029
3030   if(!pic14_sameRegs(AOP(result),AOP(right)))
3031     emitpcode(POC_BSF,  popGet(AOP(result),0));
3032
3033   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3034   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3035   emitpcode(POC_BCF,  popGet(AOP(result),0));
3036
3037 }
3038
3039
3040 /*-----------------------------------------------------------------*/
3041 /* genMultOneByte : 8 bit multiplication & division                */
3042 /*-----------------------------------------------------------------*/
3043 static void genMultOneByte (operand *left,
3044                             operand *right,
3045                             operand *result)
3046 {
3047   sym_link *opetype = operandType(result);
3048
3049   // symbol *lbl ;
3050   int size,offset;
3051
3052   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3053   DEBUGpic14_AopType(__LINE__,left,right,result);
3054   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3055
3056   /* (if two literals, the value is computed before) */
3057   /* if one literal, literal on the right */
3058   if (AOP_TYPE(left) == AOP_LIT){
3059     operand *t = right;
3060     right = left;
3061     left = t;
3062   }
3063
3064   size = AOP_SIZE(result);
3065   if(size == 1) {
3066
3067     if (AOP_TYPE(right) == AOP_LIT){
3068       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3069                      aopGet(AOP(right),0,FALSE,FALSE), 
3070                      aopGet(AOP(left),0,FALSE,FALSE), 
3071                      aopGet(AOP(result),0,FALSE,FALSE));
3072       pic14_emitcode("call","genMultLit");
3073     } else {
3074       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3075                      aopGet(AOP(right),0,FALSE,FALSE), 
3076                      aopGet(AOP(left),0,FALSE,FALSE), 
3077                      aopGet(AOP(result),0,FALSE,FALSE));
3078       pic14_emitcode("call","genMult8X8_8");
3079
3080     }
3081     genMult8X8_8 (left, right,result);
3082
3083
3084     /* signed or unsigned */
3085     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3086     //l = aopGet(AOP(left),0,FALSE,FALSE);
3087     //MOVA(l);       
3088     //pic14_emitcode("mul","ab");
3089     /* if result size = 1, mul signed = mul unsigned */
3090     //aopPut(AOP(result),"a",0);
3091
3092   } else {  // (size > 1)
3093
3094     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3095                    aopGet(AOP(right),0,FALSE,FALSE), 
3096                    aopGet(AOP(left),0,FALSE,FALSE), 
3097                    aopGet(AOP(result),0,FALSE,FALSE));
3098
3099     if (SPEC_USIGN(opetype)){
3100       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3101       genUMult8X8_16 (left, right, result, NULL);
3102
3103       if (size > 2) {
3104         /* for filling the MSBs */
3105         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3106         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3107       }
3108     }
3109     else{
3110       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3111
3112       pic14_emitcode("mov","a,b");
3113
3114       /* adjust the MSB if left or right neg */
3115
3116       /* if one literal */
3117       if (AOP_TYPE(right) == AOP_LIT){
3118         pic14_emitcode("multiply ","right is a lit");
3119         /* AND literal negative */
3120         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3121           /* adjust MSB (c==0 after mul) */
3122           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3123         }
3124       }
3125       else{
3126         genSMult8X8_16 (left, right, result, NULL);
3127       }
3128
3129       if(size > 2){
3130         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3131         /* get the sign */
3132         pic14_emitcode("rlc","a");
3133         pic14_emitcode("subb","a,acc");
3134       }
3135     }
3136
3137     size -= 2;   
3138     offset = 2;
3139     if (size > 0)
3140       while (size--)
3141         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3142     //aopPut(AOP(result),"a",offset++);
3143   }
3144 }
3145
3146 /*-----------------------------------------------------------------*/
3147 /* genMult - generates code for multiplication                     */
3148 /*-----------------------------------------------------------------*/
3149 static void genMult (iCode *ic)
3150 {
3151     operand *left = IC_LEFT(ic);
3152     operand *right = IC_RIGHT(ic);
3153     operand *result= IC_RESULT(ic);   
3154
3155     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3156     /* assign the amsops */
3157     aopOp (left,ic,FALSE);
3158     aopOp (right,ic,FALSE);
3159     aopOp (result,ic,TRUE);
3160
3161   DEBUGpic14_AopType(__LINE__,left,right,result);
3162
3163     /* special cases first */
3164     /* both are bits */
3165     if (AOP_TYPE(left) == AOP_CRY &&
3166         AOP_TYPE(right)== AOP_CRY) {
3167         genMultbits(left,right,result);
3168         goto release ;
3169     }
3170
3171     /* if both are of size == 1 */
3172     if (AOP_SIZE(left) == 1 &&
3173         AOP_SIZE(right) == 1 ) {
3174         genMultOneByte(left,right,result);
3175         goto release ;
3176     }
3177
3178     pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3179
3180     /* should have been converted to function call */
3181     //assert(0) ;
3182
3183 release :
3184     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3185     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3186     freeAsmop(result,NULL,ic,TRUE); 
3187 }
3188
3189 /*-----------------------------------------------------------------*/
3190 /* genDivbits :- division of bits                                  */
3191 /*-----------------------------------------------------------------*/
3192 static void genDivbits (operand *left, 
3193                         operand *right, 
3194                         operand *result)
3195 {
3196
3197     char *l;
3198
3199     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3200     /* the result must be bit */    
3201     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3202     l = aopGet(AOP(left),0,FALSE,FALSE);
3203
3204     MOVA(l);    
3205
3206     pic14_emitcode("div","ab");
3207     pic14_emitcode("rrc","a");
3208     aopPut(AOP(result),"c",0);
3209 }
3210
3211 /*-----------------------------------------------------------------*/
3212 /* genDivOneByte : 8 bit division                                  */
3213 /*-----------------------------------------------------------------*/
3214 static void genDivOneByte (operand *left,
3215                            operand *right,
3216                            operand *result)
3217 {
3218     sym_link *opetype = operandType(result);
3219     char *l ;
3220     symbol *lbl ;
3221     int size,offset;
3222
3223     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3224     size = AOP_SIZE(result) - 1;
3225     offset = 1;
3226     /* signed or unsigned */
3227     if (SPEC_USIGN(opetype)) {
3228         /* unsigned is easy */
3229         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3230         l = aopGet(AOP(left),0,FALSE,FALSE);
3231         MOVA(l);        
3232         pic14_emitcode("div","ab");
3233         aopPut(AOP(result),"a",0);
3234         while (size--)
3235             aopPut(AOP(result),zero,offset++);
3236         return ;
3237     }
3238
3239     /* signed is a little bit more difficult */
3240
3241     /* save the signs of the operands */
3242     l = aopGet(AOP(left),0,FALSE,FALSE);    
3243     MOVA(l);    
3244     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3245     pic14_emitcode("push","acc"); /* save it on the stack */
3246
3247     /* now sign adjust for both left & right */
3248     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3249     MOVA(l);       
3250     lbl = newiTempLabel(NULL);
3251     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3252     pic14_emitcode("cpl","a");   
3253     pic14_emitcode("inc","a");
3254     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3255     pic14_emitcode("mov","b,a");
3256
3257     /* sign adjust left side */
3258     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3259     MOVA(l);
3260
3261     lbl = newiTempLabel(NULL);
3262     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3263     pic14_emitcode("cpl","a");
3264     pic14_emitcode("inc","a");
3265     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3266
3267     /* now the division */
3268     pic14_emitcode("div","ab");
3269     /* we are interested in the lower order
3270     only */
3271     pic14_emitcode("mov","b,a");
3272     lbl = newiTempLabel(NULL);
3273     pic14_emitcode("pop","acc");   
3274     /* if there was an over flow we don't 
3275     adjust the sign of the result */
3276     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3277     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3278     CLRC;
3279     pic14_emitcode("clr","a");
3280     pic14_emitcode("subb","a,b");
3281     pic14_emitcode("mov","b,a");
3282     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3283
3284     /* now we are done */
3285     aopPut(AOP(result),"b",0);
3286     if(size > 0){
3287         pic14_emitcode("mov","c,b.7");
3288         pic14_emitcode("subb","a,acc");   
3289     }
3290     while (size--)
3291         aopPut(AOP(result),"a",offset++);
3292
3293 }
3294
3295 /*-----------------------------------------------------------------*/
3296 /* genDiv - generates code for division                            */
3297 /*-----------------------------------------------------------------*/
3298 static void genDiv (iCode *ic)
3299 {
3300     operand *left = IC_LEFT(ic);
3301     operand *right = IC_RIGHT(ic);
3302     operand *result= IC_RESULT(ic);   
3303
3304     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3305     /* assign the amsops */
3306     aopOp (left,ic,FALSE);
3307     aopOp (right,ic,FALSE);
3308     aopOp (result,ic,TRUE);
3309
3310     /* special cases first */
3311     /* both are bits */
3312     if (AOP_TYPE(left) == AOP_CRY &&
3313         AOP_TYPE(right)== AOP_CRY) {
3314         genDivbits(left,right,result);
3315         goto release ;
3316     }
3317
3318     /* if both are of size == 1 */
3319     if (AOP_SIZE(left) == 1 &&
3320         AOP_SIZE(right) == 1 ) {
3321         genDivOneByte(left,right,result);
3322         goto release ;
3323     }
3324
3325     /* should have been converted to function call */
3326     assert(0);
3327 release :
3328     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3329     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3330     freeAsmop(result,NULL,ic,TRUE); 
3331 }
3332
3333 /*-----------------------------------------------------------------*/
3334 /* genModbits :- modulus of bits                                   */
3335 /*-----------------------------------------------------------------*/
3336 static void genModbits (operand *left, 
3337                         operand *right, 
3338                         operand *result)
3339 {
3340
3341     char *l;
3342
3343     /* the result must be bit */    
3344     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3345     l = aopGet(AOP(left),0,FALSE,FALSE);
3346
3347     MOVA(l);       
3348
3349     pic14_emitcode("div","ab");
3350     pic14_emitcode("mov","a,b");
3351     pic14_emitcode("rrc","a");
3352     aopPut(AOP(result),"c",0);
3353 }
3354
3355 /*-----------------------------------------------------------------*/
3356 /* genModOneByte : 8 bit modulus                                   */
3357 /*-----------------------------------------------------------------*/
3358 static void genModOneByte (operand *left,
3359                            operand *right,
3360                            operand *result)
3361 {
3362     sym_link *opetype = operandType(result);
3363     char *l ;
3364     symbol *lbl ;
3365
3366     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3367     /* signed or unsigned */
3368     if (SPEC_USIGN(opetype)) {
3369         /* unsigned is easy */
3370         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3371         l = aopGet(AOP(left),0,FALSE,FALSE);
3372         MOVA(l);    
3373         pic14_emitcode("div","ab");
3374         aopPut(AOP(result),"b",0);
3375         return ;
3376     }
3377
3378     /* signed is a little bit more difficult */
3379
3380     /* save the signs of the operands */
3381     l = aopGet(AOP(left),0,FALSE,FALSE);    
3382     MOVA(l);
3383
3384     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3385     pic14_emitcode("push","acc"); /* save it on the stack */
3386
3387     /* now sign adjust for both left & right */
3388     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3389     MOVA(l);
3390
3391     lbl = newiTempLabel(NULL);
3392     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3393     pic14_emitcode("cpl","a");   
3394     pic14_emitcode("inc","a");
3395     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3396     pic14_emitcode("mov","b,a"); 
3397
3398     /* sign adjust left side */
3399     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3400     MOVA(l);
3401
3402     lbl = newiTempLabel(NULL);
3403     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3404     pic14_emitcode("cpl","a");   
3405     pic14_emitcode("inc","a");
3406     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3407
3408     /* now the multiplication */
3409     pic14_emitcode("div","ab");
3410     /* we are interested in the lower order
3411     only */
3412     lbl = newiTempLabel(NULL);
3413     pic14_emitcode("pop","acc");   
3414     /* if there was an over flow we don't 
3415     adjust the sign of the result */
3416     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3417     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3418     CLRC ;
3419     pic14_emitcode("clr","a");
3420     pic14_emitcode("subb","a,b");
3421     pic14_emitcode("mov","b,a");
3422     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3423
3424     /* now we are done */
3425     aopPut(AOP(result),"b",0);
3426
3427 }
3428
3429 /*-----------------------------------------------------------------*/
3430 /* genMod - generates code for division                            */
3431 /*-----------------------------------------------------------------*/
3432 static void genMod (iCode *ic)
3433 {
3434     operand *left = IC_LEFT(ic);
3435     operand *right = IC_RIGHT(ic);
3436     operand *result= IC_RESULT(ic);  
3437
3438     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3439     /* assign the amsops */
3440     aopOp (left,ic,FALSE);
3441     aopOp (right,ic,FALSE);
3442     aopOp (result,ic,TRUE);
3443
3444     /* special cases first */
3445     /* both are bits */
3446     if (AOP_TYPE(left) == AOP_CRY &&
3447         AOP_TYPE(right)== AOP_CRY) {
3448         genModbits(left,right,result);
3449         goto release ;
3450     }
3451
3452     /* if both are of size == 1 */
3453     if (AOP_SIZE(left) == 1 &&
3454         AOP_SIZE(right) == 1 ) {
3455         genModOneByte(left,right,result);
3456         goto release ;
3457     }
3458
3459     /* should have been converted to function call */
3460     assert(0);
3461
3462 release :
3463     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3464     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3465     freeAsmop(result,NULL,ic,TRUE); 
3466 }
3467
3468 /*-----------------------------------------------------------------*/
3469 /* genIfxJump :- will create a jump depending on the ifx           */
3470 /*-----------------------------------------------------------------*/
3471 /*
3472   note: May need to add parameter to indicate when a variable is in bit space.
3473 */
3474 static void genIfxJump (iCode *ic, char *jval)
3475 {
3476
3477     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3478     /* if true label then we jump if condition
3479     supplied is true */
3480     if ( IC_TRUE(ic) ) {
3481
3482         if(strcmp(jval,"a") == 0)
3483           emitSKPZ;
3484         else if (strcmp(jval,"c") == 0)
3485           emitSKPC;
3486         else {
3487           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3488           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3489         }
3490
3491         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3492         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3493
3494     }
3495     else {
3496         /* false label is present */
3497         if(strcmp(jval,"a") == 0)
3498           emitSKPNZ;
3499         else if (strcmp(jval,"c") == 0)
3500           emitSKPNC;
3501         else {
3502           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3503           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3504         }
3505
3506         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3507         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3508
3509     }
3510
3511
3512     /* mark the icode as generated */
3513     ic->generated = 1;
3514 }
3515
3516 /*-----------------------------------------------------------------*/
3517 /* genSkip                                                         */
3518 /*-----------------------------------------------------------------*/
3519 static void genSkip(iCode *ifx,int status_bit)
3520 {
3521   if(!ifx)
3522     return;
3523
3524   if ( IC_TRUE(ifx) ) {
3525     switch(status_bit) {
3526     case 'z':
3527       emitSKPNZ;
3528       break;
3529
3530     case 'c':
3531       emitSKPNC;
3532       break;
3533
3534     case 'd':
3535       emitSKPDC;
3536       break;
3537
3538     }
3539
3540     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3541     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3542
3543   } else {
3544
3545     switch(status_bit) {
3546
3547     case 'z':
3548       emitSKPZ;
3549       break;
3550
3551     case 'c':
3552       emitSKPC;
3553       break;
3554
3555     case 'd':
3556       emitSKPDC;
3557       break;
3558     }
3559     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3560     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3561
3562   }
3563
3564 }
3565
3566 /*-----------------------------------------------------------------*/
3567 /* genSkipc                                                        */
3568 /*-----------------------------------------------------------------*/
3569 static void genSkipc(resolvedIfx *rifx)
3570 {
3571   if(!rifx)
3572     return;
3573
3574   if(rifx->condition)
3575     emitSKPC;
3576   else
3577     emitSKPNC;
3578
3579   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3580   rifx->generated = 1;
3581 }
3582
3583 /*-----------------------------------------------------------------*/
3584 /* genSkipz2                                                       */
3585 /*-----------------------------------------------------------------*/
3586 static void genSkipz2(resolvedIfx *rifx)
3587 {
3588   if(!rifx)
3589     return;
3590
3591   if(rifx->condition)
3592     emitSKPZ;
3593   else
3594     emitSKPNZ;
3595
3596   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3597   rifx->generated = 1;
3598 }
3599
3600 /*-----------------------------------------------------------------*/
3601 /* genSkipz                                                        */
3602 /*-----------------------------------------------------------------*/
3603 static void genSkipz(iCode *ifx, int condition)
3604 {
3605   if(!ifx)
3606     return;
3607
3608   if(condition)
3609     emitSKPNZ;
3610   else
3611     emitSKPZ;
3612
3613   if ( IC_TRUE(ifx) )
3614     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3615   else
3616     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3617
3618   if ( IC_TRUE(ifx) )
3619     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3620   else
3621     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3622
3623 }
3624 /*-----------------------------------------------------------------*/
3625 /* genSkipCond                                                     */
3626 /*-----------------------------------------------------------------*/
3627 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3628 {
3629   if(!rifx)
3630     return;
3631
3632   if(rifx->condition)
3633     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3634   else
3635     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3636
3637
3638   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3639   rifx->generated = 1;
3640 }
3641
3642 #if 0
3643 /*-----------------------------------------------------------------*/
3644 /* genChkZeroes :- greater or less than comparison                 */
3645 /*     For each byte in a literal that is zero, inclusive or the   */
3646 /*     the corresponding byte in the operand with W                */
3647 /*     returns true if any of the bytes are zero                   */
3648 /*-----------------------------------------------------------------*/
3649 static int genChkZeroes(operand *op, int lit,  int size)
3650 {
3651
3652   int i;
3653   int flag =1;
3654
3655   while(size--) {
3656     i = (lit >> (size*8)) & 0xff;
3657
3658     if(i==0) {
3659       if(flag) 
3660         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3661       else
3662         emitpcode(POC_IORFW, popGet(AOP(op),size));
3663       flag = 0;
3664     }
3665   }
3666
3667   return (flag==0);
3668 }
3669 #endif
3670
3671 /*-----------------------------------------------------------------*/
3672 /* genCmp :- greater or less than comparison                       */
3673 /*-----------------------------------------------------------------*/
3674 static void genCmp (operand *left,operand *right,
3675                     operand *result, iCode *ifx, int sign)
3676 {
3677   int size; //, offset = 0 ;
3678   unsigned long lit = 0L,i = 0;
3679   resolvedIfx rFalseIfx;
3680   //  resolvedIfx rTrueIfx;
3681   symbol *truelbl;
3682   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3683   if(ifx) {
3684   DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3685   DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3686   }
3687
3688
3689   resolveIfx(&rFalseIfx,ifx);
3690   truelbl  = newiTempLabel(NULL);
3691
3692   //if(IC_TRUE(ifx) == NULL)
3693   /* if left & right are bit variables */
3694   if (AOP_TYPE(left) == AOP_CRY &&
3695       AOP_TYPE(right) == AOP_CRY ) {
3696     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3697     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3698   } else {
3699     /* subtract right from left if at the
3700        end the carry flag is set then we know that
3701        left is greater than right */
3702     size = max(AOP_SIZE(left),AOP_SIZE(right));
3703
3704     /* if unsigned char cmp with lit, do cjne left,#right,zz */
3705     //if((size == 1) && !sign &&
3706     //   (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3707     //  symbol *lbl  = newiTempLabel(NULL);
3708     //  pic14_emitcode("cjne","%s,%s,%05d_DS_",
3709     //       aopGet(AOP(left),offset,FALSE,FALSE),
3710     //       aopGet(AOP(right),offset,FALSE,FALSE),
3711     //       lbl->key+100);
3712     //pic14_emitcode("","%05d_DS_:",lbl->key+100);
3713     //} else 
3714       {
3715
3716       symbol *lbl  = newiTempLabel(NULL);
3717
3718       if(AOP_TYPE(right) == AOP_LIT) {
3719
3720         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3721
3722         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3723
3724         /* special cases */
3725
3726         if(lit == 0) {
3727
3728           if(sign != 0) 
3729             genSkipCond(&rFalseIfx,left,size-1,7);
3730           else 
3731             /* no need to compare to 0...*/
3732             /* NOTE: this is a de-generate compare that most certainly 
3733              *       creates some dead code. */
3734             emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3735
3736           if(ifx) ifx->generated = 1;
3737           return;
3738
3739         }
3740         size--;
3741
3742         if(size == 0) {
3743           //i = (lit >> (size*8)) & 0xff;
3744           DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3745         
3746           emitpcode(POC_MOVFW, popGet(AOP(left),size));
3747
3748           i = ((0-lit) & 0xff);
3749           if(sign) {
3750             if( i == 0x81) { 
3751               /* lit is 0x7f, all signed chars are less than
3752                * this except for 0x7f itself */
3753               emitpcode(POC_XORLW, popGetLit(0x7f));
3754               genSkipz2(&rFalseIfx);
3755             } else {
3756               emitpcode(POC_ADDLW, popGetLit(0x80));
3757               emitpcode(POC_ADDLW, popGetLit(i^0x80));
3758               genSkipc(&rFalseIfx);
3759             }
3760
3761           } else {
3762             emitpcode(POC_ADDLW, popGetLit(i));
3763             genSkipc(&rFalseIfx);
3764
3765           }
3766
3767           if(ifx) ifx->generated = 1;
3768           return;
3769         }
3770
3771         /* chars are out of the way. now do ints and longs */
3772
3773
3774         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3775         
3776         /* special cases */
3777
3778         if(sign) {
3779
3780           if(lit == 0) {
3781             genSkipCond(&rFalseIfx,left,size,7);
3782             if(ifx) ifx->generated = 1;
3783             return;
3784           }
3785
3786           if(lit <0x100) {
3787             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3788
3789             //rFalseIfx.condition ^= 1;
3790             //genSkipCond(&rFalseIfx,left,size,7);
3791             //rFalseIfx.condition ^= 1;
3792
3793             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3794             if(rFalseIfx.condition)
3795               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3796             else
3797               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3798
3799             emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3800             emitpcode(POC_ADDFW, popGet(AOP(left),0));
3801             emitpcode(POC_MOVFW, popGet(AOP(left),1));
3802
3803             while(size > 1)
3804               emitpcode(POC_IORFW, popGet(AOP(left),size--));
3805
3806             if(rFalseIfx.condition) {
3807               emitSKPZ;
3808               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3809
3810             } else {
3811               emitSKPNZ;
3812             }
3813
3814             genSkipc(&rFalseIfx);
3815             emitpLabel(truelbl->key);
3816             if(ifx) ifx->generated = 1;
3817             return;
3818
3819           }
3820
3821           if(size == 1) {
3822
3823             if( (lit & 0xff) == 0) {
3824               /* lower byte is zero */
3825               DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3826               i = ((lit >> 8) & 0xff) ^0x80;
3827               emitpcode(POC_MOVFW, popGet(AOP(left),size));
3828               emitpcode(POC_ADDLW, popGetLit( 0x80));
3829               emitpcode(POC_ADDLW, popGetLit(0x100-i));
3830               genSkipc(&rFalseIfx);
3831
3832
3833               if(ifx) ifx->generated = 1;
3834               return;
3835
3836             }
3837           } else {
3838             /* Special cases for signed longs */
3839             if( (lit & 0xffffff) == 0) {
3840               /* lower byte is zero */
3841               DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3842               i = ((lit >> 8*3) & 0xff) ^0x80;
3843               emitpcode(POC_MOVFW, popGet(AOP(left),size));
3844               emitpcode(POC_ADDLW, popGetLit( 0x80));
3845               emitpcode(POC_ADDLW, popGetLit(0x100-i));
3846               genSkipc(&rFalseIfx);
3847
3848
3849               if(ifx) ifx->generated = 1;
3850               return;
3851
3852             }
3853
3854           }
3855
3856
3857           if(lit & (0x80 << (size*8))) {
3858             /* lit is negative */
3859             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3860
3861             //genSkipCond(&rFalseIfx,left,size,7);
3862
3863             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3864
3865             if(rFalseIfx.condition)
3866               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3867             else
3868               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3869
3870
3871           } else {
3872             /* lit is positive */
3873             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3874             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3875             if(rFalseIfx.condition)
3876               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3877             else
3878               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3879
3880             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3881             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3882             //rFalseIfx.condition ^= 1;
3883             //genSkipCond(&rFalseIfx,left,size,7);
3884             //rFalseIfx.condition ^= 1;
3885           }
3886
3887           /*
3888             This works, but is only good for ints.
3889             It also requires a "known zero" register.
3890             emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3891             emitpcode(POC_ADDFW, popGet(AOP(left),0));
3892             emitpcode(POC_RLFW,  popCopyReg(&pc_kzero));
3893             emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
3894             emitpcode(POC_ADDFW, popGet(AOP(left),1));
3895             genSkipc(&rFalseIfx);
3896
3897             emitpLabel(truelbl->key);
3898             if(ifx) ifx->generated = 1;
3899             return;
3900           **/
3901           
3902           /* There are no more special cases, so perform a general compare */
3903   
3904           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3905           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3906
3907           while(size--) {
3908
3909             emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3910             emitSKPNZ;
3911             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3912           }
3913           //rFalseIfx.condition ^= 1;
3914           genSkipc(&rFalseIfx);
3915
3916           emitpLabel(truelbl->key);
3917
3918           if(ifx) ifx->generated = 1;
3919           return;
3920
3921
3922         }
3923
3924
3925         /* sign is out of the way. So now do an unsigned compare */
3926         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3927
3928
3929         //genChkZeroes(left)
3930
3931         /* General case - compare to an unsigned literal on the right.*/
3932
3933         i = (lit >> (size*8)) & 0xff;
3934         emitpcode(POC_MOVLW, popGetLit(i));
3935         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3936         while(size--) {
3937           i = (lit >> (size*8)) & 0xff;
3938
3939           if(i) {
3940             emitpcode(POC_MOVLW, popGetLit(i));
3941             emitSKPNZ;
3942             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3943           } else {
3944             /* this byte of the lit is zero, 
3945              *if it's not the last then OR in the variable */
3946             if(size)
3947               emitpcode(POC_IORFW, popGet(AOP(left),size));
3948           }
3949         }
3950
3951
3952         emitpLabel(lbl->key);
3953         //if(emitFinalCheck)
3954           genSkipc(&rFalseIfx);
3955         if(sign)
3956           emitpLabel(truelbl->key);
3957
3958         if(ifx) ifx->generated = 1;
3959         return;
3960
3961
3962       }
3963
3964       if(AOP_TYPE(left) == AOP_LIT) {
3965         //symbol *lbl = newiTempLabel(NULL);
3966
3967         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3968
3969
3970         DEBUGpic14_emitcode(";left lit","lit = %d,sign=%d",lit,sign);
3971
3972         /* Special cases */
3973         if((lit == 0) && (sign == 0)){
3974
3975           size--;
3976           emitpcode(POC_MOVFW, popGet(AOP(right),size));
3977           while(size) 
3978             emitpcode(POC_IORFW, popGet(AOP(right),--size));
3979
3980           //rFalseIfx.condition ^= 1;
3981           genSkipz2(&rFalseIfx);
3982           if(ifx) ifx->generated = 1;
3983           return;
3984         }
3985
3986         if(size==1) {
3987           /* Special cases */
3988           lit &= 0xff;
3989           if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3990             /* degenerate compare can never be true */
3991             if(rFalseIfx.condition == 0)
3992               emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3993
3994             if(ifx) ifx->generated = 1;
3995             return;
3996           }
3997
3998           if(sign) {
3999             if((lit+1)&0xff) {
4000               emitpcode(POC_MOVFW, popGet(AOP(right),0));
4001               emitpcode(POC_ADDLW, popGetLit(0x80));
4002               emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4003               rFalseIfx.condition ^= 1;
4004               genSkipc(&rFalseIfx);
4005             } else {
4006               rFalseIfx.condition ^= 1;
4007               genSkipCond(&rFalseIfx,right,0,7);
4008             }
4009             
4010           } else {
4011             if(lit & 0xff) {
4012               emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4013               emitpcode(POC_SUBFW, popGet(AOP(right),0));
4014               DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4015               rFalseIfx.condition ^= 1;
4016               genSkipc(&rFalseIfx);
4017             } else { 
4018               emitpcode(POC_MOVFW, popGet(AOP(right),0));
4019               genSkipz2(&rFalseIfx);
4020             }
4021           }
4022
4023           if(ifx) ifx->generated = 1;
4024           return;
4025
4026         } else {
4027
4028           /* Size is greater than 1 */
4029
4030
4031
4032           if(sign) {
4033             int lp1 = lit+1;
4034
4035             size--;
4036
4037             if(lp1 == 0) {
4038               /* this means lit = 0xffffffff, or -1 */
4039
4040
4041               DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4042               rFalseIfx.condition ^= 1;
4043               genSkipCond(&rFalseIfx,right,size,7);
4044               if(ifx) ifx->generated = 1;
4045               return;
4046             }
4047
4048             if(lit == 0) {
4049               int s = size;
4050
4051               if(rFalseIfx.condition) {
4052                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4053                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4054               }
4055
4056               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4057               while(size--)
4058                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4059
4060
4061               emitSKPZ;
4062               if(rFalseIfx.condition) {
4063                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4064                 emitpLabel(truelbl->key);
4065               }else {
4066                 rFalseIfx.condition ^= 1;
4067                 genSkipCond(&rFalseIfx,right,s,7);
4068               }
4069
4070               if(ifx) ifx->generated = 1;
4071               return;
4072             }
4073
4074
4075             if(lit & (0x80 << (size*8))) {
4076               /* Lit is less than zero */
4077               DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4078               //rFalseIfx.condition ^= 1;
4079               //genSkipCond(&rFalseIfx,left,size,7);
4080               //rFalseIfx.condition ^= 1;
4081               emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4082               //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4083
4084               if(rFalseIfx.condition)
4085                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4086               else
4087                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4088
4089
4090             } else {
4091               /* Lit is greater than or equal to zero */
4092               DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4093               //rFalseIfx.condition ^= 1;
4094               //genSkipCond(&rFalseIfx,right,size,7);
4095               //rFalseIfx.condition ^= 1;
4096
4097               //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4098               //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4099
4100               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4101               if(rFalseIfx.condition)
4102                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4103               else
4104                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4105
4106             }
4107             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4108             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4109
4110             while(size--) {
4111
4112               emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4113               emitSKPNZ;
4114               emitpcode(POC_SUBFW, popGet(AOP(right),size));
4115             }
4116             rFalseIfx.condition ^= 1;
4117             //rFalseIfx.condition = 1;
4118             genSkipc(&rFalseIfx);
4119
4120             emitpLabel(truelbl->key);
4121
4122             if(ifx) ifx->generated = 1;
4123             return;
4124
4125           } else {
4126             /* Unsigned compare for sizes greater than 1 */
4127
4128             while(size--) {
4129               i = (lit >> (size*8)) & 0xff;
4130
4131
4132               if(size) {
4133                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4134                 emitpcode(POC_MOVLW, popGetLit(i&0xff));
4135                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4136                 emitSKPZ;
4137                 emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4138               } else {
4139                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4140                 emitpcode(POC_MOVLW, popGetLit((i+1)&0xff));
4141                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4142
4143               }
4144             }
4145
4146             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4147
4148             emitpLabel(lbl->key);
4149
4150             rFalseIfx.condition ^= 1;
4151             genSkipc(&rFalseIfx);
4152
4153           }
4154         if(sign)
4155           emitpLabel(truelbl->key);
4156         if(ifx) ifx->generated = 1;
4157         return;
4158         }
4159       }
4160       /* Compare two variables */
4161
4162       DEBUGpic14_emitcode(";sign","%d",sign);
4163
4164       size--;
4165       if(sign) {
4166         /* Sigh. thus sucks... */
4167         if(size) {
4168           emitpcode(POC_MOVFW, popGet(AOP(left),size));
4169           emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4170           emitpcode(POC_MOVLW, popGetLit(0x80));
4171           emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4172           emitpcode(POC_XORFW, popGet(AOP(right),size));
4173           emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4174         } else {
4175           /* Signed char comparison */
4176           /* Special thanks to Nikolai Golovchenko for this snippet */
4177           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4178           emitpcode(POC_SUBFW, popGet(AOP(left),0));
4179           emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4180           emitpcode(POC_XORFW, popGet(AOP(left),0));
4181           emitpcode(POC_XORFW, popGet(AOP(right),0));
4182           emitpcode(POC_ADDLW, popGetLit(0x80));
4183
4184           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4185           genSkipc(&rFalseIfx);
4186           
4187           if(ifx) ifx->generated = 1;
4188           return;
4189         }
4190
4191       } else {
4192
4193         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4194         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4195       }
4196
4197
4198       /* The rest of the bytes of a multi-byte compare */
4199       while (size) {
4200
4201         emitSKPZ;
4202         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4203         size--;
4204
4205         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4206         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4207
4208
4209       }
4210
4211       emitpLabel(lbl->key);
4212
4213       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4214       genSkipc(&rFalseIfx);
4215       if(ifx) ifx->generated = 1;
4216       return;
4217
4218     }
4219   }
4220
4221   //release:
4222   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4223     pic14_outBitC(result);
4224   } else {
4225     /* if the result is used in the next
4226        ifx conditional branch then generate
4227        code a little differently */
4228     if (ifx )
4229       genIfxJump (ifx,"c");
4230     else
4231       pic14_outBitC(result);
4232     /* leave the result in acc */
4233   }
4234
4235 }
4236
4237 /*-----------------------------------------------------------------*/
4238 /* genCmpGt :- greater than comparison                             */
4239 /*-----------------------------------------------------------------*/
4240 static void genCmpGt (iCode *ic, iCode *ifx)
4241 {
4242     operand *left, *right, *result;
4243     sym_link *letype , *retype;
4244     int sign ;
4245
4246     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4247     left = IC_LEFT(ic);
4248     right= IC_RIGHT(ic);
4249     result = IC_RESULT(ic);
4250
4251     letype = getSpec(operandType(left));
4252     retype =getSpec(operandType(right));
4253     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4254     /* assign the amsops */
4255     aopOp (left,ic,FALSE);
4256     aopOp (right,ic,FALSE);
4257     aopOp (result,ic,TRUE);
4258
4259     genCmp(right, left, result, ifx, sign);
4260
4261     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4262     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4263     freeAsmop(result,NULL,ic,TRUE); 
4264 }
4265
4266 /*-----------------------------------------------------------------*/
4267 /* genCmpLt - less than comparisons                                */
4268 /*-----------------------------------------------------------------*/
4269 static void genCmpLt (iCode *ic, iCode *ifx)
4270 {
4271     operand *left, *right, *result;
4272     sym_link *letype , *retype;
4273     int sign ;
4274
4275     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4276     left = IC_LEFT(ic);
4277     right= IC_RIGHT(ic);
4278     result = IC_RESULT(ic);
4279
4280     letype = getSpec(operandType(left));
4281     retype =getSpec(operandType(right));
4282     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4283
4284     /* assign the amsops */
4285     aopOp (left,ic,FALSE);
4286     aopOp (right,ic,FALSE);
4287     aopOp (result,ic,TRUE);
4288
4289     genCmp(left, right, result, ifx, sign);
4290
4291     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4292     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4293     freeAsmop(result,NULL,ic,TRUE); 
4294 }
4295
4296 /*-----------------------------------------------------------------*/
4297 /* genc16bit2lit - compare a 16 bit value to a literal             */
4298 /*-----------------------------------------------------------------*/
4299 static void genc16bit2lit(operand *op, int lit, int offset)
4300 {
4301   int i;
4302
4303   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4304   if( (lit&0xff) == 0) 
4305     i=1;
4306   else
4307     i=0;
4308
4309   switch( BYTEofLONG(lit,i)) { 
4310   case 0:
4311     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4312     break;
4313   case 1:
4314     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4315     break;
4316   case 0xff:
4317     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4318     break;
4319   default:
4320     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4321     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4322   }
4323
4324   i ^= 1;
4325
4326   switch( BYTEofLONG(lit,i)) { 
4327   case 0:
4328     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4329     break;
4330   case 1:
4331     emitSKPNZ;
4332     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4333     break;
4334   case 0xff:
4335     emitSKPNZ;
4336     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4337     break;
4338   default:
4339     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4340     emitSKPNZ;
4341     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4342
4343   }
4344
4345 }
4346
4347 /*-----------------------------------------------------------------*/
4348 /* gencjneshort - compare and jump if not equal                    */
4349 /*-----------------------------------------------------------------*/
4350 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4351 {
4352   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4353   int offset = 0;
4354   resolvedIfx rIfx;
4355   symbol *lbl;
4356
4357   unsigned long lit = 0L;
4358   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4359   DEBUGpic14_AopType(__LINE__,left,right,NULL);
4360
4361   resolveIfx(&rIfx,ifx);
4362   lbl =  newiTempLabel(NULL);
4363
4364
4365   /* if the left side is a literal or 
4366      if the right is in a pointer register and left 
4367      is not */
4368   if ((AOP_TYPE(left) == AOP_LIT) || 
4369       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4370     operand *t = right;
4371     right = left;
4372     left = t;
4373   }
4374   if(AOP_TYPE(right) == AOP_LIT)
4375     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4376
4377   /* if the right side is a literal then anything goes */
4378   if (AOP_TYPE(right) == AOP_LIT &&
4379       AOP_TYPE(left) != AOP_DIR ) {
4380     switch(size) {
4381     case 2:
4382       genc16bit2lit(left, lit, 0);
4383       emitSKPNZ;
4384       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4385       break;
4386     default:
4387       while (size--) {
4388         if(lit & 0xff) {
4389           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4390           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4391         } else {
4392           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4393         }
4394
4395         emitSKPNZ;
4396         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4397         offset++;
4398         lit >>= 8;
4399       }
4400       break;
4401     }
4402   }
4403
4404   /* if the right side is in a register or in direct space or
4405      if the left is a pointer register & right is not */    
4406   else if (AOP_TYPE(right) == AOP_REG ||
4407            AOP_TYPE(right) == AOP_DIR || 
4408            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4409            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4410     switch(size) {
4411     case 2:
4412       genc16bit2lit(left, lit, 0);
4413       emitSKPNZ;
4414       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4415       break;
4416     default:
4417       while (size--) {
4418         int emit_skip=1;
4419         if((AOP_TYPE(left) == AOP_DIR) && 
4420            ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4421
4422           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4423           emitpcode(POC_XORFW,popGet(AOP(right),offset));
4424
4425         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4426             
4427           switch (lit & 0xff) {
4428           case 0:
4429             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4430             break;
4431           case 1:
4432             emitpcode(POC_DECFSZ,popGet(AOP(left),offset));
4433             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4434             emit_skip=0;
4435             break;
4436           case 0xff:
4437             emitpcode(POC_INCFSZ,popGet(AOP(left),offset));
4438             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4439             emit_skip=0;
4440             break;
4441           default:
4442             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4443             emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4444           }
4445           lit >>= 8;
4446
4447         } else {
4448           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4449         }
4450         if(emit_skip) {
4451           if(AOP_TYPE(result) == AOP_CRY) {
4452             pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4453             if(rIfx.condition)
4454               emitSKPNZ;
4455             else
4456               emitSKPZ;
4457             emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4458           } else {
4459             /* fix me. probably need to check result size too */
4460             emitpcode(POC_CLRF,popGet(AOP(result),0));
4461             if(rIfx.condition)
4462               emitSKPNZ;
4463             else
4464               emitSKPZ;
4465             emitpcode(POC_INCF,popGet(AOP(result),0));
4466           }
4467           if(ifx)
4468             ifx->generated=1;
4469         }
4470         emit_skip++;
4471         offset++;
4472       }
4473       break;
4474     }
4475   } else if(AOP_TYPE(right) == AOP_REG &&
4476             AOP_TYPE(left) != AOP_DIR){
4477
4478     while(size--) {
4479       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4480       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4481       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4482       if(rIfx.condition)
4483         emitSKPNZ;
4484       else
4485         emitSKPZ;
4486       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4487       offset++;
4488     }
4489       
4490   }else{
4491     /* right is a pointer reg need both a & b */
4492     while(size--) {
4493       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4494       if(strcmp(l,"b"))
4495         pic14_emitcode("mov","b,%s",l);
4496       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4497       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4498       offset++;
4499     }
4500   }
4501   emitpLabel(lbl->key);
4502
4503   if(ifx)
4504     ifx->generated = 1;
4505 }
4506
4507 #if 0
4508 /*-----------------------------------------------------------------*/
4509 /* gencjne - compare and jump if not equal                         */
4510 /*-----------------------------------------------------------------*/
4511 static void gencjne(operand *left, operand *right, iCode *ifx)
4512 {
4513     symbol *tlbl  = newiTempLabel(NULL);
4514
4515     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4516     gencjneshort(left, right, lbl);
4517
4518     pic14_emitcode("mov","a,%s",one);
4519     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4520     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4521     pic14_emitcode("clr","a");
4522     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4523
4524     emitpLabel(lbl->key);
4525     emitpLabel(tlbl->key);
4526
4527 }
4528 #endif
4529
4530 /*-----------------------------------------------------------------*/
4531 /* genCmpEq - generates code for equal to                          */
4532 /*-----------------------------------------------------------------*/
4533 static void genCmpEq (iCode *ic, iCode *ifx)
4534 {
4535     operand *left, *right, *result;
4536     unsigned long lit = 0L;
4537     int size,offset=0;
4538
4539     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4540
4541     if(ifx)
4542       DEBUGpic14_emitcode ("; ifx is non-null","");
4543     else
4544       DEBUGpic14_emitcode ("; ifx is null","");
4545
4546     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4547     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4548     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4549
4550     size = max(AOP_SIZE(left),AOP_SIZE(right));
4551
4552     DEBUGpic14_AopType(__LINE__,left,right,result);
4553
4554     /* if literal, literal on the right or 
4555     if the right is in a pointer register and left 
4556     is not */
4557     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4558         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4559       operand *tmp = right ;
4560       right = left;
4561       left = tmp;
4562     }
4563
4564
4565     if(ifx && !AOP_SIZE(result)){
4566         symbol *tlbl;
4567         /* if they are both bit variables */
4568         if (AOP_TYPE(left) == AOP_CRY &&
4569             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4570             if(AOP_TYPE(right) == AOP_LIT){
4571                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4572                 if(lit == 0L){
4573                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4574                     pic14_emitcode("cpl","c");
4575                 } else if(lit == 1L) {
4576                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4577                 } else {
4578                     pic14_emitcode("clr","c");
4579                 }
4580                 /* AOP_TYPE(right) == AOP_CRY */
4581             } else {
4582                 symbol *lbl = newiTempLabel(NULL);
4583                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4584                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4585                 pic14_emitcode("cpl","c");
4586                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4587             }
4588             /* if true label then we jump if condition
4589             supplied is true */
4590             tlbl = newiTempLabel(NULL);
4591             if ( IC_TRUE(ifx) ) {
4592                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4593                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4594             } else {
4595                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4596                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4597             }
4598             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4599
4600             {
4601               /* left and right are both bit variables, result is carry */
4602               resolvedIfx rIfx;
4603               
4604               resolveIfx(&rIfx,ifx);
4605
4606               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4607               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4608               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4609               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4610               genSkipz2(&rIfx);
4611             }
4612         } else {
4613
4614           /* They're not both bit variables. Is the right a literal? */
4615           if(AOP_TYPE(right) == AOP_LIT) {
4616             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4617             
4618             switch(size) {
4619
4620             case 1:
4621               switch(lit & 0xff) {
4622               case 1:
4623                 if ( IC_TRUE(ifx) ) {
4624                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4625                   emitSKPNZ;
4626                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4627                 } else {
4628                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4629                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4630                 }
4631                 break;
4632               case 0xff:
4633                 if ( IC_TRUE(ifx) ) {
4634                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4635                   emitSKPNZ;
4636                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4637                 } else {
4638                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4639                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4640                 }
4641                 break;
4642               default:
4643                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4644                 if(lit)
4645                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4646                 genSkip(ifx,'z');
4647               }
4648
4649
4650               /* end of size == 1 */
4651               break;
4652               
4653             case 2:
4654               genc16bit2lit(left,lit,offset);
4655               genSkip(ifx,'z');
4656               break;
4657               /* end of size == 2 */
4658
4659             default:
4660               /* size is 4 */
4661               if(lit==0) {
4662                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4663                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4664                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4665                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4666
4667               } else {
4668
4669                 /* search for patterns that can be optimized */
4670
4671                 genc16bit2lit(left,lit,0);
4672                 lit >>= 16;
4673                 if(lit) {
4674                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4675                   //genSkip(ifx,'z');
4676                   genc16bit2lit(left,lit,2);
4677                 } else {
4678                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4679                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4680
4681                 }
4682                 
4683               }
4684
4685               genSkip(ifx,'z');
4686             }
4687           
4688             ifx->generated = 1;
4689             goto release ;
4690             
4691
4692           } else if(AOP_TYPE(right) == AOP_CRY ) {
4693             /* we know the left is not a bit, but that the right is */
4694             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4695             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4696                       popGet(AOP(right),offset));
4697             emitpcode(POC_XORLW,popGetLit(1));
4698
4699             /* if the two are equal, then W will be 0 and the Z bit is set
4700              * we could test Z now, or go ahead and check the high order bytes if
4701              * the variable we're comparing is larger than a byte. */
4702
4703             while(--size)
4704               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4705
4706             if ( IC_TRUE(ifx) ) {
4707               emitSKPNZ;
4708               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4709               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4710             } else {
4711               emitSKPZ;
4712               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4713               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4714             }
4715
4716           } else {
4717             /* They're both variables that are larger than bits */
4718             int s = size;
4719
4720             tlbl = newiTempLabel(NULL);
4721
4722             while(size--) {
4723               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4724               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4725
4726               if ( IC_TRUE(ifx) ) {
4727                 if(size) {
4728                   emitSKPZ;
4729                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4730                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4731                 } else {
4732                   emitSKPNZ;
4733                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4734                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4735                 }
4736               } else {
4737                 emitSKPZ;
4738                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4739                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4740               }
4741               offset++;
4742             }
4743             if(s>1 && IC_TRUE(ifx)) {
4744               emitpLabel(tlbl->key);
4745               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4746             }
4747           }
4748         }
4749         /* mark the icode as generated */
4750         ifx->generated = 1;
4751         goto release ;
4752     }
4753
4754     /* if they are both bit variables */
4755     if (AOP_TYPE(left) == AOP_CRY &&
4756         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4757         if(AOP_TYPE(right) == AOP_LIT){
4758             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4759             if(lit == 0L){
4760                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4761                 pic14_emitcode("cpl","c");
4762             } else if(lit == 1L) {
4763                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4764             } else {
4765                 pic14_emitcode("clr","c");
4766             }
4767             /* AOP_TYPE(right) == AOP_CRY */
4768         } else {
4769             symbol *lbl = newiTempLabel(NULL);
4770             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4771             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4772             pic14_emitcode("cpl","c");
4773             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4774         }
4775         /* c = 1 if egal */
4776         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4777             pic14_outBitC(result);
4778             goto release ;
4779         }
4780         if (ifx) {
4781             genIfxJump (ifx,"c");
4782             goto release ;
4783         }
4784         /* if the result is used in an arithmetic operation
4785         then put the result in place */
4786         pic14_outBitC(result);
4787     } else {
4788       
4789       gencjne(left,right,result,ifx);
4790 /*
4791       if(ifx) 
4792         gencjne(left,right,newiTempLabel(NULL));
4793       else {
4794         if(IC_TRUE(ifx)->key)
4795           gencjne(left,right,IC_TRUE(ifx)->key);
4796         else
4797           gencjne(left,right,IC_FALSE(ifx)->key);
4798         ifx->generated = 1;
4799         goto release ;
4800       }
4801       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4802         aopPut(AOP(result),"a",0);
4803         goto release ;
4804       }
4805
4806       if (ifx) {
4807         genIfxJump (ifx,"a");
4808         goto release ;
4809       }
4810 */
4811       /* if the result is used in an arithmetic operation
4812          then put the result in place */
4813 /*
4814       if (AOP_TYPE(result) != AOP_CRY) 
4815         pic14_outAcc(result);
4816 */
4817       /* leave the result in acc */
4818     }
4819
4820 release:
4821     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4822     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4823     freeAsmop(result,NULL,ic,TRUE);
4824 }
4825
4826 /*-----------------------------------------------------------------*/
4827 /* ifxForOp - returns the icode containing the ifx for operand     */
4828 /*-----------------------------------------------------------------*/
4829 static iCode *ifxForOp ( operand *op, iCode *ic )
4830 {
4831     /* if true symbol then needs to be assigned */
4832     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4833     if (IS_TRUE_SYMOP(op))
4834         return NULL ;
4835
4836     /* if this has register type condition and
4837     the next instruction is ifx with the same operand
4838     and live to of the operand is upto the ifx only then */
4839     if (ic->next &&
4840         ic->next->op == IFX &&
4841         IC_COND(ic->next)->key == op->key &&
4842         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4843         return ic->next;
4844
4845     if (ic->next &&
4846         ic->next->op == IFX &&
4847         IC_COND(ic->next)->key == op->key) {
4848       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4849       return ic->next;
4850     }
4851
4852     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4853     if (ic->next &&
4854         ic->next->op == IFX)
4855       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4856
4857     if (ic->next &&
4858         ic->next->op == IFX &&
4859         IC_COND(ic->next)->key == op->key) {
4860       DEBUGpic14_emitcode ("; "," key is okay");
4861       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4862                            OP_SYMBOL(op)->liveTo,
4863                            ic->next->seq);
4864     }
4865
4866
4867     return NULL;
4868 }
4869 /*-----------------------------------------------------------------*/
4870 /* genAndOp - for && operation                                     */
4871 /*-----------------------------------------------------------------*/
4872 static void genAndOp (iCode *ic)
4873 {
4874     operand *left,*right, *result;
4875     symbol *tlbl;
4876
4877     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4878     /* note here that && operations that are in an
4879     if statement are taken away by backPatchLabels
4880     only those used in arthmetic operations remain */
4881     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4882     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4883     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4884
4885     /* if both are bit variables */
4886     if (AOP_TYPE(left) == AOP_CRY &&
4887         AOP_TYPE(right) == AOP_CRY ) {
4888         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4889         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4890         pic14_outBitC(result);
4891     } else {
4892         tlbl = newiTempLabel(NULL);
4893         pic14_toBoolean(left);    
4894         pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
4895         pic14_toBoolean(right);
4896         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4897         pic14_outBitAcc(result);
4898     }
4899
4900     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4901     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4902     freeAsmop(result,NULL,ic,TRUE);
4903 }
4904
4905
4906 /*-----------------------------------------------------------------*/
4907 /* genOrOp - for || operation                                      */
4908 /*-----------------------------------------------------------------*/
4909 /*
4910   tsd pic port -
4911   modified this code, but it doesn't appear to ever get called
4912 */
4913
4914 static void genOrOp (iCode *ic)
4915 {
4916     operand *left,*right, *result;
4917     symbol *tlbl;
4918
4919     /* note here that || operations that are in an
4920     if statement are taken away by backPatchLabels
4921     only those used in arthmetic operations remain */
4922     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4923     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4924     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4925     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4926
4927     DEBUGpic14_AopType(__LINE__,left,right,result);
4928
4929     /* if both are bit variables */
4930     if (AOP_TYPE(left) == AOP_CRY &&
4931         AOP_TYPE(right) == AOP_CRY ) {
4932       pic14_emitcode("clrc","");
4933       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
4934                AOP(left)->aopu.aop_dir,
4935                AOP(left)->aopu.aop_dir);
4936       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4937                AOP(right)->aopu.aop_dir,
4938                AOP(right)->aopu.aop_dir);
4939       pic14_emitcode("setc","");
4940
4941     } else {
4942         tlbl = newiTempLabel(NULL);
4943         pic14_toBoolean(left);
4944         emitSKPZ;
4945         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4946         pic14_toBoolean(right);
4947         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4948
4949         pic14_outBitAcc(result);
4950     }
4951
4952     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4953     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4954     freeAsmop(result,NULL,ic,TRUE);            
4955 }
4956
4957 /*-----------------------------------------------------------------*/
4958 /* isLiteralBit - test if lit == 2^n                               */
4959 /*-----------------------------------------------------------------*/
4960 static int isLiteralBit(unsigned long lit)
4961 {
4962     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4963     0x100L,0x200L,0x400L,0x800L,
4964     0x1000L,0x2000L,0x4000L,0x8000L,
4965     0x10000L,0x20000L,0x40000L,0x80000L,
4966     0x100000L,0x200000L,0x400000L,0x800000L,
4967     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4968     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4969     int idx;
4970     
4971     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4972     for(idx = 0; idx < 32; idx++)
4973         if(lit == pw[idx])
4974             return idx+1;
4975     return 0;
4976 }
4977
4978 /*-----------------------------------------------------------------*/
4979 /* continueIfTrue -                                                */
4980 /*-----------------------------------------------------------------*/
4981 static void continueIfTrue (iCode *ic)
4982 {
4983     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4984     if(IC_TRUE(ic))
4985         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4986     ic->generated = 1;
4987 }
4988
4989 /*-----------------------------------------------------------------*/
4990 /* jmpIfTrue -                                                     */
4991 /*-----------------------------------------------------------------*/
4992 static void jumpIfTrue (iCode *ic)
4993 {
4994     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4995     if(!IC_TRUE(ic))
4996         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4997     ic->generated = 1;
4998 }
4999
5000 /*-----------------------------------------------------------------*/
5001 /* jmpTrueOrFalse -                                                */
5002 /*-----------------------------------------------------------------*/
5003 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5004 {
5005     // ugly but optimized by peephole
5006     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5007     if(IC_TRUE(ic)){
5008         symbol *nlbl = newiTempLabel(NULL);
5009         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5010         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5011         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5012         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5013     }
5014     else{
5015         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5016         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5017     }
5018     ic->generated = 1;
5019 }
5020
5021 /*-----------------------------------------------------------------*/
5022 /* genAnd  - code for and                                          */
5023 /*-----------------------------------------------------------------*/
5024 static void genAnd (iCode *ic, iCode *ifx)
5025 {
5026   operand *left, *right, *result;
5027   int size, offset=0;  
5028   unsigned long lit = 0L;
5029   int bytelit = 0;
5030   resolvedIfx rIfx;
5031
5032
5033   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5034   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5035   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5036   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5037
5038   resolveIfx(&rIfx,ifx);
5039
5040   /* if left is a literal & right is not then exchange them */
5041   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5042       AOP_NEEDSACC(left)) {
5043     operand *tmp = right ;
5044     right = left;
5045     left = tmp;
5046   }
5047
5048   /* if result = right then exchange them */
5049   if(pic14_sameRegs(AOP(result),AOP(right))){
5050     operand *tmp = right ;
5051     right = left;
5052     left = tmp;
5053   }
5054
5055   /* if right is bit then exchange them */
5056   if (AOP_TYPE(right) == AOP_CRY &&
5057       AOP_TYPE(left) != AOP_CRY){
5058     operand *tmp = right ;
5059     right = left;
5060     left = tmp;
5061   }
5062   if(AOP_TYPE(right) == AOP_LIT)
5063     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5064
5065   size = AOP_SIZE(result);
5066
5067   DEBUGpic14_AopType(__LINE__,left,right,result);
5068
5069   // if(bit & yy)
5070   // result = bit & yy;
5071   if (AOP_TYPE(left) == AOP_CRY){
5072     // c = bit & literal;
5073     if(AOP_TYPE(right) == AOP_LIT){
5074       if(lit & 1) {
5075         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5076           // no change
5077           goto release;
5078         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5079       } else {
5080         // bit(result) = 0;
5081         if(size && (AOP_TYPE(result) == AOP_CRY)){
5082           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5083           goto release;
5084         }
5085         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5086           jumpIfTrue(ifx);
5087           goto release;
5088         }
5089         pic14_emitcode("clr","c");
5090       }
5091     } else {
5092       if (AOP_TYPE(right) == AOP_CRY){
5093         // c = bit & bit;
5094         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5095         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5096       } else {
5097         // c = bit & val;
5098         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5099         // c = lsb
5100         pic14_emitcode("rrc","a");
5101         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5102       }
5103     }
5104     // bit = c
5105     // val = c
5106     if(size)
5107       pic14_outBitC(result);
5108     // if(bit & ...)
5109     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5110       genIfxJump(ifx, "c");           
5111     goto release ;
5112   }
5113
5114   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5115   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5116   if((AOP_TYPE(right) == AOP_LIT) &&
5117      (AOP_TYPE(result) == AOP_CRY) &&
5118      (AOP_TYPE(left) != AOP_CRY)){
5119     int posbit = isLiteralBit(lit);
5120     /* left &  2^n */
5121     if(posbit){
5122       posbit--;
5123       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5124       // bit = left & 2^n
5125       if(size)
5126         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5127       // if(left &  2^n)
5128       else{
5129         if(ifx){
5130 /*
5131           if(IC_TRUE(ifx)) {
5132             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5133             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
5134           } else {
5135             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5136             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
5137           }
5138 */
5139           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5140                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5141           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5142           
5143           ifx->generated = 1;
5144         }
5145         goto release;
5146       }
5147     } else {
5148       symbol *tlbl = newiTempLabel(NULL);
5149       int sizel = AOP_SIZE(left);
5150       if(size)
5151         pic14_emitcode("setb","c");
5152       while(sizel--){
5153         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5154           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5155           // byte ==  2^n ?
5156           if((posbit = isLiteralBit(bytelit)) != 0)
5157             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5158           else{
5159             if(bytelit != 0x0FFL)
5160               pic14_emitcode("anl","a,%s",
5161                              aopGet(AOP(right),offset,FALSE,TRUE));
5162             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5163           }
5164         }
5165         offset++;
5166       }
5167       // bit = left & literal
5168       if(size){
5169         pic14_emitcode("clr","c");
5170         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5171       }
5172       // if(left & literal)
5173       else{
5174         if(ifx)
5175           jmpTrueOrFalse(ifx, tlbl);
5176         goto release ;
5177       }
5178     }
5179     pic14_outBitC(result);
5180     goto release ;
5181   }
5182
5183   /* if left is same as result */
5184   if(pic14_sameRegs(AOP(result),AOP(left))){
5185     int know_W = -1;
5186     for(;size--; offset++,lit>>=8) {
5187       if(AOP_TYPE(right) == AOP_LIT){
5188         switch(lit & 0xff) {
5189         case 0x00:
5190           /*  and'ing with 0 has clears the result */
5191           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5192           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5193           break;
5194         case 0xff:
5195           /* and'ing with 0xff is a nop when the result and left are the same */
5196           break;
5197
5198         default:
5199           {
5200             int p = my_powof2( (~lit) & 0xff );
5201             if(p>=0) {
5202               /* only one bit is set in the literal, so use a bcf instruction */
5203               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5204               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5205
5206             } else {
5207               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5208               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5209               if(know_W != (lit&0xff))
5210                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5211               know_W = lit &0xff;
5212               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5213             }
5214           }    
5215         }
5216       } else {
5217         if (AOP_TYPE(left) == AOP_ACC) {
5218           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5219         } else {                    
5220           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5221           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5222
5223         }
5224       }
5225     }
5226
5227   } else {
5228     // left & result in different registers
5229     if(AOP_TYPE(result) == AOP_CRY){
5230       // result = bit
5231       // if(size), result in bit
5232       // if(!size && ifx), conditional oper: if(left & right)
5233       symbol *tlbl = newiTempLabel(NULL);
5234       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5235       if(size)
5236         pic14_emitcode("setb","c");
5237       while(sizer--){
5238         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5239         pic14_emitcode("anl","a,%s",
5240                        aopGet(AOP(left),offset,FALSE,FALSE));
5241         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5242         offset++;
5243       }
5244       if(size){
5245         CLRC;
5246         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5247         pic14_outBitC(result);
5248       } else if(ifx)
5249         jmpTrueOrFalse(ifx, tlbl);
5250     } else {
5251       for(;(size--);offset++) {
5252         // normal case
5253         // result = left & right
5254         if(AOP_TYPE(right) == AOP_LIT){
5255           int t = (lit >> (offset*8)) & 0x0FFL;
5256           switch(t) { 
5257           case 0x00:
5258             pic14_emitcode("clrf","%s",
5259                            aopGet(AOP(result),offset,FALSE,FALSE));
5260             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5261             break;
5262           case 0xff:
5263             pic14_emitcode("movf","%s,w",
5264                            aopGet(AOP(left),offset,FALSE,FALSE));
5265             pic14_emitcode("movwf","%s",
5266                            aopGet(AOP(result),offset,FALSE,FALSE));
5267             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5268             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5269             break;
5270           default:
5271             pic14_emitcode("movlw","0x%x",t);
5272             pic14_emitcode("andwf","%s,w",
5273                            aopGet(AOP(left),offset,FALSE,FALSE));
5274             pic14_emitcode("movwf","%s",
5275                            aopGet(AOP(result),offset,FALSE,FALSE));
5276               
5277             emitpcode(POC_MOVLW, popGetLit(t));
5278             emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5279             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5280           }
5281           continue;
5282         }
5283
5284         if (AOP_TYPE(left) == AOP_ACC) {
5285           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5286           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5287         } else {
5288           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5289           pic14_emitcode("andwf","%s,w",
5290                          aopGet(AOP(left),offset,FALSE,FALSE));
5291           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5292           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5293         }
5294         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5295         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5296       }
5297     }
5298   }
5299
5300   release :
5301     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5302   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5303   freeAsmop(result,NULL,ic,TRUE);     
5304 }
5305
5306 /*-----------------------------------------------------------------*/
5307 /* genOr  - code for or                                            */
5308 /*-----------------------------------------------------------------*/
5309 static void genOr (iCode *ic, iCode *ifx)
5310 {
5311     operand *left, *right, *result;
5312     int size, offset=0;
5313     unsigned long lit = 0L;
5314
5315     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5316
5317     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5318     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5319     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5320
5321     DEBUGpic14_AopType(__LINE__,left,right,result);
5322
5323     /* if left is a literal & right is not then exchange them */
5324     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5325         AOP_NEEDSACC(left)) {
5326         operand *tmp = right ;
5327         right = left;
5328         left = tmp;
5329     }
5330
5331     /* if result = right then exchange them */
5332     if(pic14_sameRegs(AOP(result),AOP(right))){
5333         operand *tmp = right ;
5334         right = left;
5335         left = tmp;
5336     }
5337
5338     /* if right is bit then exchange them */
5339     if (AOP_TYPE(right) == AOP_CRY &&
5340         AOP_TYPE(left) != AOP_CRY){
5341         operand *tmp = right ;
5342         right = left;
5343         left = tmp;
5344     }
5345
5346     DEBUGpic14_AopType(__LINE__,left,right,result);
5347
5348     if(AOP_TYPE(right) == AOP_LIT)
5349         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5350
5351     size = AOP_SIZE(result);
5352
5353     // if(bit | yy)
5354     // xx = bit | yy;
5355     if (AOP_TYPE(left) == AOP_CRY){
5356         if(AOP_TYPE(right) == AOP_LIT){
5357             // c = bit & literal;
5358             if(lit){
5359                 // lit != 0 => result = 1
5360                 if(AOP_TYPE(result) == AOP_CRY){
5361                   if(size)
5362                     emitpcode(POC_BSF, popGet(AOP(result),0));
5363                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5364                   //     AOP(result)->aopu.aop_dir,
5365                   //     AOP(result)->aopu.aop_dir);
5366                     else if(ifx)
5367                         continueIfTrue(ifx);
5368                     goto release;
5369                 }
5370             } else {
5371                 // lit == 0 => result = left
5372                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5373                     goto release;
5374                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5375             }
5376         } else {
5377             if (AOP_TYPE(right) == AOP_CRY){
5378               if(pic14_sameRegs(AOP(result),AOP(left))){
5379                 // c = bit | bit;
5380                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5381                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5382                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5383
5384                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5385                          AOP(result)->aopu.aop_dir,
5386                          AOP(result)->aopu.aop_dir);
5387                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5388                          AOP(right)->aopu.aop_dir,
5389                          AOP(right)->aopu.aop_dir);
5390                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5391                          AOP(result)->aopu.aop_dir,
5392                          AOP(result)->aopu.aop_dir);
5393               } else {
5394                 if( AOP_TYPE(result) == AOP_ACC) {
5395                   emitpcode(POC_MOVLW, popGetLit(0));
5396                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5397                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5398                   emitpcode(POC_MOVLW, popGetLit(1));
5399
5400                 } else {
5401
5402                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5403                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5404                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5405                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5406
5407                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5408                                  AOP(result)->aopu.aop_dir,
5409                                  AOP(result)->aopu.aop_dir);
5410                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5411                                  AOP(right)->aopu.aop_dir,
5412                                  AOP(right)->aopu.aop_dir);
5413                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5414                                  AOP(left)->aopu.aop_dir,
5415                                  AOP(left)->aopu.aop_dir);
5416                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5417                                  AOP(result)->aopu.aop_dir,
5418                                  AOP(result)->aopu.aop_dir);
5419                 }
5420               }
5421             } else {
5422                 // c = bit | val;
5423                 symbol *tlbl = newiTempLabel(NULL);
5424                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5425
5426
5427                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5428                 if( AOP_TYPE(right) == AOP_ACC) {
5429                   emitpcode(POC_IORLW, popGetLit(0));
5430                   emitSKPNZ;
5431                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5432                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5433                 }
5434
5435
5436
5437                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5438                     pic14_emitcode(";XXX setb","c");
5439                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5440                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5441                 pic14_toBoolean(right);
5442                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5443                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5444                     jmpTrueOrFalse(ifx, tlbl);
5445                     goto release;
5446                 } else {
5447                     CLRC;
5448                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5449                 }
5450             }
5451         }
5452         // bit = c
5453         // val = c
5454         if(size)
5455             pic14_outBitC(result);
5456         // if(bit | ...)
5457         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5458             genIfxJump(ifx, "c");           
5459         goto release ;
5460     }
5461
5462     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5463     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5464     if((AOP_TYPE(right) == AOP_LIT) &&
5465        (AOP_TYPE(result) == AOP_CRY) &&
5466        (AOP_TYPE(left) != AOP_CRY)){
5467         if(lit){
5468           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5469             // result = 1
5470             if(size)
5471                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5472             else 
5473                 continueIfTrue(ifx);
5474             goto release;
5475         } else {
5476           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5477             // lit = 0, result = boolean(left)
5478             if(size)
5479                 pic14_emitcode(";XXX setb","c");
5480             pic14_toBoolean(right);
5481             if(size){
5482                 symbol *tlbl = newiTempLabel(NULL);
5483                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5484                 CLRC;
5485                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5486             } else {
5487                 genIfxJump (ifx,"a");
5488                 goto release;
5489             }
5490         }
5491         pic14_outBitC(result);
5492         goto release ;
5493     }
5494
5495     /* if left is same as result */
5496     if(pic14_sameRegs(AOP(result),AOP(left))){
5497       int know_W = -1;
5498       for(;size--; offset++,lit>>=8) {
5499         if(AOP_TYPE(right) == AOP_LIT){
5500           if((lit & 0xff) == 0)
5501             /*  or'ing with 0 has no effect */
5502             continue;
5503           else {
5504             int p = my_powof2(lit & 0xff);
5505             if(p>=0) {
5506               /* only one bit is set in the literal, so use a bsf instruction */
5507               emitpcode(POC_BSF,
5508                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5509             } else {
5510               if(know_W != (lit & 0xff))
5511                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5512               know_W = lit & 0xff;
5513               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5514             }
5515                     
5516           }
5517         } else {
5518           if (AOP_TYPE(left) == AOP_ACC) {
5519             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5520             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5521           } else {                  
5522             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5523             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5524
5525             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5526             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5527
5528           }
5529         }
5530       }
5531     } else {
5532         // left & result in different registers
5533         if(AOP_TYPE(result) == AOP_CRY){
5534             // result = bit
5535             // if(size), result in bit
5536             // if(!size && ifx), conditional oper: if(left | right)
5537             symbol *tlbl = newiTempLabel(NULL);
5538             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5539             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5540
5541
5542             if(size)
5543                 pic14_emitcode(";XXX setb","c");
5544             while(sizer--){
5545                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5546                 pic14_emitcode(";XXX orl","a,%s",
5547                          aopGet(AOP(left),offset,FALSE,FALSE));
5548                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5549                 offset++;
5550             }
5551             if(size){
5552                 CLRC;
5553                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5554                 pic14_outBitC(result);
5555             } else if(ifx)
5556                 jmpTrueOrFalse(ifx, tlbl);
5557         } else for(;(size--);offset++){
5558           // normal case
5559           // result = left & right
5560           if(AOP_TYPE(right) == AOP_LIT){
5561             int t = (lit >> (offset*8)) & 0x0FFL;
5562             switch(t) { 
5563             case 0x00:
5564               emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5565               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5566
5567               pic14_emitcode("movf","%s,w",
5568                        aopGet(AOP(left),offset,FALSE,FALSE));
5569               pic14_emitcode("movwf","%s",
5570                        aopGet(AOP(result),offset,FALSE,FALSE));
5571               break;
5572             default:
5573               emitpcode(POC_MOVLW,  popGetLit(t));
5574               emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5575               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5576
5577               pic14_emitcode("movlw","0x%x",t);
5578               pic14_emitcode("iorwf","%s,w",
5579                        aopGet(AOP(left),offset,FALSE,FALSE));
5580               pic14_emitcode("movwf","%s",
5581                        aopGet(AOP(result),offset,FALSE,FALSE));
5582               
5583             }
5584             continue;
5585           }
5586
5587           // faster than result <- left, anl result,right
5588           // and better if result is SFR
5589           if (AOP_TYPE(left) == AOP_ACC) {
5590             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5591             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5592           } else {
5593             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5594             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5595
5596             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5597             pic14_emitcode("iorwf","%s,w",
5598                      aopGet(AOP(left),offset,FALSE,FALSE));
5599           }
5600           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5601           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5602         }
5603     }
5604
5605 release :
5606     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5607     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5608     freeAsmop(result,NULL,ic,TRUE);     
5609 }
5610
5611 /*-----------------------------------------------------------------*/
5612 /* genXor - code for xclusive or                                   */
5613 /*-----------------------------------------------------------------*/
5614 static void genXor (iCode *ic, iCode *ifx)
5615 {
5616   operand *left, *right, *result;
5617   int size, offset=0;
5618   unsigned long lit = 0L;
5619
5620   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5621
5622   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5623   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5624   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5625
5626   /* if left is a literal & right is not ||
5627      if left needs acc & right does not */
5628   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5629       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5630     operand *tmp = right ;
5631     right = left;
5632     left = tmp;
5633   }
5634
5635   /* if result = right then exchange them */
5636   if(pic14_sameRegs(AOP(result),AOP(right))){
5637     operand *tmp = right ;
5638     right = left;
5639     left = tmp;
5640   }
5641
5642   /* if right is bit then exchange them */
5643   if (AOP_TYPE(right) == AOP_CRY &&
5644       AOP_TYPE(left) != AOP_CRY){
5645     operand *tmp = right ;
5646     right = left;
5647     left = tmp;
5648   }
5649   if(AOP_TYPE(right) == AOP_LIT)
5650     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5651
5652   size = AOP_SIZE(result);
5653
5654   // if(bit ^ yy)
5655   // xx = bit ^ yy;
5656   if (AOP_TYPE(left) == AOP_CRY){
5657     if(AOP_TYPE(right) == AOP_LIT){
5658       // c = bit & literal;
5659       if(lit>>1){
5660         // lit>>1  != 0 => result = 1
5661         if(AOP_TYPE(result) == AOP_CRY){
5662           if(size)
5663             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5664             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5665           else if(ifx)
5666             continueIfTrue(ifx);
5667           goto release;
5668         }
5669         pic14_emitcode("setb","c");
5670       } else{
5671         // lit == (0 or 1)
5672         if(lit == 0){
5673           // lit == 0, result = left
5674           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5675             goto release;
5676           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5677         } else{
5678           // lit == 1, result = not(left)
5679           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5680             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5681             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5682             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5683             goto release;
5684           } else {
5685             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5686             pic14_emitcode("cpl","c");
5687           }
5688         }
5689       }
5690
5691     } else {
5692       // right != literal
5693       symbol *tlbl = newiTempLabel(NULL);
5694       if (AOP_TYPE(right) == AOP_CRY){
5695         // c = bit ^ bit;
5696         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5697       }
5698       else{
5699         int sizer = AOP_SIZE(right);
5700         // c = bit ^ val
5701         // if val>>1 != 0, result = 1
5702         pic14_emitcode("setb","c");
5703         while(sizer){
5704           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5705           if(sizer == 1)
5706             // test the msb of the lsb
5707             pic14_emitcode("anl","a,#0xfe");
5708           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5709           sizer--;
5710         }
5711         // val = (0,1)
5712         pic14_emitcode("rrc","a");
5713       }
5714       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5715       pic14_emitcode("cpl","c");
5716       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5717     }
5718     // bit = c
5719     // val = c
5720     if(size)
5721       pic14_outBitC(result);
5722     // if(bit | ...)
5723     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5724       genIfxJump(ifx, "c");           
5725     goto release ;
5726   }
5727
5728   if(pic14_sameRegs(AOP(result),AOP(left))){
5729     /* if left is same as result */
5730     for(;size--; offset++) {
5731       if(AOP_TYPE(right) == AOP_LIT){
5732         int t  = (lit >> (offset*8)) & 0x0FFL;
5733         if(t == 0x00L)
5734           continue;
5735         else
5736           if (IS_AOP_PREG(left)) {
5737             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5738             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5739             aopPut(AOP(result),"a",offset);
5740           } else {
5741             emitpcode(POC_MOVLW, popGetLit(t));
5742             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5743             pic14_emitcode("xrl","%s,%s",
5744                            aopGet(AOP(left),offset,FALSE,TRUE),
5745                            aopGet(AOP(right),offset,FALSE,FALSE));
5746           }
5747       } else {
5748         if (AOP_TYPE(left) == AOP_ACC)
5749           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5750         else {
5751           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5752           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5753 /*
5754           if (IS_AOP_PREG(left)) {
5755             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5756             aopPut(AOP(result),"a",offset);
5757           } else
5758             pic14_emitcode("xrl","%s,a",
5759                            aopGet(AOP(left),offset,FALSE,TRUE));
5760 */
5761         }
5762       }
5763     }
5764   } else {
5765     // left & result in different registers
5766     if(AOP_TYPE(result) == AOP_CRY){
5767       // result = bit
5768       // if(size), result in bit
5769       // if(!size && ifx), conditional oper: if(left ^ right)
5770       symbol *tlbl = newiTempLabel(NULL);
5771       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5772       if(size)
5773         pic14_emitcode("setb","c");
5774       while(sizer--){
5775         if((AOP_TYPE(right) == AOP_LIT) &&
5776            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5777           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5778         } else {
5779           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5780           pic14_emitcode("xrl","a,%s",
5781                          aopGet(AOP(left),offset,FALSE,FALSE));
5782         }
5783         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5784         offset++;
5785       }
5786       if(size){
5787         CLRC;
5788         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5789         pic14_outBitC(result);
5790       } else if(ifx)
5791         jmpTrueOrFalse(ifx, tlbl);
5792     } else for(;(size--);offset++){
5793       // normal case
5794       // result = left & right
5795       if(AOP_TYPE(right) == AOP_LIT){
5796         int t = (lit >> (offset*8)) & 0x0FFL;
5797         switch(t) { 
5798         case 0x00:
5799           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5800           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5801           pic14_emitcode("movf","%s,w",
5802                          aopGet(AOP(left),offset,FALSE,FALSE));
5803           pic14_emitcode("movwf","%s",
5804                          aopGet(AOP(result),offset,FALSE,FALSE));
5805           break;
5806         case 0xff:
5807           emitpcode(POC_COMFW,popGet(AOP(left),offset));
5808           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5809           pic14_emitcode("comf","%s,w",
5810                          aopGet(AOP(left),offset,FALSE,FALSE));
5811           pic14_emitcode("movwf","%s",
5812                          aopGet(AOP(result),offset,FALSE,FALSE));
5813           break;
5814         default:
5815           emitpcode(POC_MOVLW, popGetLit(t));
5816           emitpcode(POC_XORFW,popGet(AOP(left),offset));
5817           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5818           pic14_emitcode("movlw","0x%x",t);
5819           pic14_emitcode("xorwf","%s,w",
5820                          aopGet(AOP(left),offset,FALSE,FALSE));
5821           pic14_emitcode("movwf","%s",
5822                          aopGet(AOP(result),offset,FALSE,FALSE));
5823
5824         }
5825         continue;
5826       }
5827
5828       // faster than result <- left, anl result,right
5829       // and better if result is SFR
5830       if (AOP_TYPE(left) == AOP_ACC) {
5831         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5832         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5833       } else {
5834         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5835         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5836         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5837         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5838       }
5839       if ( AOP_TYPE(result) != AOP_ACC){
5840         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5841         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5842       }
5843     }
5844   }
5845
5846   release :
5847     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5848   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5849   freeAsmop(result,NULL,ic,TRUE);     
5850 }
5851
5852 /*-----------------------------------------------------------------*/
5853 /* genInline - write the inline code out                           */
5854 /*-----------------------------------------------------------------*/
5855 static void genInline (iCode *ic)
5856 {
5857     char *buffer, *bp, *bp1;
5858     
5859     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5860
5861     _G.inLine += (!options.asmpeep);
5862
5863     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5864     strcpy(buffer,IC_INLINE(ic));
5865
5866     /* emit each line as a code */
5867     while (*bp) {
5868         if (*bp == '\n') {
5869             *bp++ = '\0';
5870             pic14_emitcode(bp1,"");
5871             addpCode2pBlock(pb,newpCodeInlineP(bp1));
5872             bp1 = bp;
5873         } else {
5874             if (*bp == ':') {
5875                 bp++;
5876                 *bp = '\0';
5877                 bp++;
5878                 pic14_emitcode(bp1,"");
5879                 bp1 = bp;
5880             } else
5881                 bp++;
5882         }
5883     }
5884     if (bp1 != bp) {
5885         pic14_emitcode(bp1,"");
5886         addpCode2pBlock(pb,newpCodeInlineP(bp1));
5887     }
5888     /*     pic14_emitcode("",buffer); */
5889     _G.inLine -= (!options.asmpeep);
5890 }
5891
5892 /*-----------------------------------------------------------------*/
5893 /* genRRC - rotate right with carry                                */
5894 /*-----------------------------------------------------------------*/
5895 static void genRRC (iCode *ic)
5896 {
5897   operand *left , *result ;
5898   int size, offset = 0, same;
5899
5900   /* rotate right with carry */
5901   left = IC_LEFT(ic);
5902   result=IC_RESULT(ic);
5903   aopOp (left,ic,FALSE);
5904   aopOp (result,ic,FALSE);
5905
5906   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5907
5908   same = pic14_sameRegs(AOP(result),AOP(left));
5909
5910   size = AOP_SIZE(result);    
5911
5912   /* get the lsb and put it into the carry */
5913   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
5914
5915   offset = 0 ;
5916
5917   while(size--) {
5918
5919     if(same) {
5920       emitpcode(POC_RRF, popGet(AOP(left),offset));
5921     } else {
5922       emitpcode(POC_RRFW, popGet(AOP(left),offset));
5923       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5924     }
5925
5926     offset++;
5927   }
5928
5929   freeAsmop(left,NULL,ic,TRUE);
5930   freeAsmop(result,NULL,ic,TRUE);
5931 }
5932
5933 /*-----------------------------------------------------------------*/
5934 /* genRLC - generate code for rotate left with carry               */
5935 /*-----------------------------------------------------------------*/
5936 static void genRLC (iCode *ic)
5937 {    
5938   operand *left , *result ;
5939   int size, offset = 0;
5940   int same;
5941
5942   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5943   /* rotate right with carry */
5944   left = IC_LEFT(ic);
5945   result=IC_RESULT(ic);
5946   aopOp (left,ic,FALSE);
5947   aopOp (result,ic,FALSE);
5948
5949   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5950
5951   same = pic14_sameRegs(AOP(result),AOP(left));
5952
5953   /* move it to the result */
5954   size = AOP_SIZE(result);    
5955
5956   /* get the msb and put it into the carry */
5957   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
5958
5959   offset = 0 ;
5960
5961   while(size--) {
5962
5963     if(same) {
5964       emitpcode(POC_RLF, popGet(AOP(left),offset));
5965     } else {
5966       emitpcode(POC_RLFW, popGet(AOP(left),offset));
5967       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5968     }
5969
5970     offset++;
5971   }
5972
5973
5974   freeAsmop(left,NULL,ic,TRUE);
5975   freeAsmop(result,NULL,ic,TRUE);
5976 }
5977
5978 /*-----------------------------------------------------------------*/
5979 /* genGetHbit - generates code get highest order bit               */
5980 /*-----------------------------------------------------------------*/
5981 static void genGetHbit (iCode *ic)
5982 {
5983     operand *left, *result;
5984     left = IC_LEFT(ic);
5985     result=IC_RESULT(ic);
5986     aopOp (left,ic,FALSE);
5987     aopOp (result,ic,FALSE);
5988
5989     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5990     /* get the highest order byte into a */
5991     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5992     if(AOP_TYPE(result) == AOP_CRY){
5993         pic14_emitcode("rlc","a");
5994         pic14_outBitC(result);
5995     }
5996     else{
5997         pic14_emitcode("rl","a");
5998         pic14_emitcode("anl","a,#0x01");
5999         pic14_outAcc(result);
6000     }
6001
6002
6003     freeAsmop(left,NULL,ic,TRUE);
6004     freeAsmop(result,NULL,ic,TRUE);
6005 }
6006
6007 /*-----------------------------------------------------------------*/
6008 /* AccRol - rotate left accumulator by known count                 */
6009 /*-----------------------------------------------------------------*/
6010 static void AccRol (int shCount)
6011 {
6012     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6013     shCount &= 0x0007;              // shCount : 0..7
6014     switch(shCount){
6015         case 0 :
6016             break;
6017         case 1 :
6018             pic14_emitcode("rl","a");
6019             break;
6020         case 2 :
6021             pic14_emitcode("rl","a");
6022             pic14_emitcode("rl","a");
6023             break;
6024         case 3 :
6025             pic14_emitcode("swap","a");
6026             pic14_emitcode("rr","a");
6027             break;
6028         case 4 :
6029             pic14_emitcode("swap","a");
6030             break;
6031         case 5 :
6032             pic14_emitcode("swap","a");
6033             pic14_emitcode("rl","a");
6034             break;
6035         case 6 :
6036             pic14_emitcode("rr","a");
6037             pic14_emitcode("rr","a");
6038             break;
6039         case 7 :
6040             pic14_emitcode("rr","a");
6041             break;
6042     }
6043 }
6044
6045 /*-----------------------------------------------------------------*/
6046 /* AccLsh - left shift accumulator by known count                  */
6047 /*-----------------------------------------------------------------*/
6048 static void AccLsh (int shCount)
6049 {
6050     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6051     if(shCount != 0){
6052         if(shCount == 1)
6053             pic14_emitcode("add","a,acc");
6054         else 
6055             if(shCount == 2) {
6056             pic14_emitcode("add","a,acc");
6057             pic14_emitcode("add","a,acc");
6058         } else {
6059             /* rotate left accumulator */
6060             AccRol(shCount);
6061             /* and kill the lower order bits */
6062             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6063         }
6064     }
6065 }
6066
6067 /*-----------------------------------------------------------------*/
6068 /* AccRsh - right shift accumulator by known count                 */
6069 /*-----------------------------------------------------------------*/
6070 static void AccRsh (int shCount)
6071 {
6072     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6073     if(shCount != 0){
6074         if(shCount == 1){
6075             CLRC;
6076             pic14_emitcode("rrc","a");
6077         } else {
6078             /* rotate right accumulator */
6079             AccRol(8 - shCount);
6080             /* and kill the higher order bits */
6081             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6082         }
6083     }
6084 }
6085
6086 #if 0
6087 /*-----------------------------------------------------------------*/
6088 /* AccSRsh - signed right shift accumulator by known count                 */
6089 /*-----------------------------------------------------------------*/
6090 static void AccSRsh (int shCount)
6091 {
6092     symbol *tlbl ;
6093     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6094     if(shCount != 0){
6095         if(shCount == 1){
6096             pic14_emitcode("mov","c,acc.7");
6097             pic14_emitcode("rrc","a");
6098         } else if(shCount == 2){
6099             pic14_emitcode("mov","c,acc.7");
6100             pic14_emitcode("rrc","a");
6101             pic14_emitcode("mov","c,acc.7");
6102             pic14_emitcode("rrc","a");
6103         } else {
6104             tlbl = newiTempLabel(NULL);
6105             /* rotate right accumulator */
6106             AccRol(8 - shCount);
6107             /* and kill the higher order bits */
6108             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6109             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6110             pic14_emitcode("orl","a,#0x%02x",
6111                      (unsigned char)~SRMask[shCount]);
6112             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6113         }
6114     }
6115 }
6116 #endif
6117 /*-----------------------------------------------------------------*/
6118 /* shiftR1Left2Result - shift right one byte from left to result   */
6119 /*-----------------------------------------------------------------*/
6120 static void shiftR1Left2ResultSigned (operand *left, int offl,
6121                                 operand *result, int offr,
6122                                 int shCount)
6123 {
6124   int same;
6125
6126   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6127
6128   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6129
6130   switch(shCount) {
6131   case 1:
6132     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6133     if(same) 
6134       emitpcode(POC_RRF, popGet(AOP(result),offr));
6135     else {
6136       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6137       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6138     }
6139
6140     break;
6141   case 2:
6142
6143     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6144     if(same) 
6145       emitpcode(POC_RRF, popGet(AOP(result),offr));
6146     else {
6147       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6148       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6149     }
6150     emitpcode(POC_RLFW, popGet(AOP(result),offl));
6151     emitpcode(POC_RRF,  popGet(AOP(result),offl));
6152
6153     break;
6154
6155   case 3:
6156     if(same)
6157       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6158     else {
6159       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6160       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6161     }
6162
6163     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6164     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6165     emitpcode(POC_ANDLW, popGetLit(0x1f));
6166
6167     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6168     emitpcode(POC_IORLW, popGetLit(0xe0));
6169
6170     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6171     break;
6172
6173   case 4:
6174     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6175     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6176     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6177     emitpcode(POC_IORLW,  popGetLit(0xf0));
6178     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6179     break;
6180   case 5:
6181     if(same) {
6182       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6183     } else {
6184       emitpcode(POC_SWAPFW,  popGet(AOP(result),offr));
6185       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6186     }
6187     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6188     emitpcode(POC_ANDLW,  popGetLit(0x07));
6189     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6190     emitpcode(POC_IORLW,  popGetLit(0xf8));
6191     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6192
6193
6194
6195     break;
6196
6197   case 6:
6198     if(same) {
6199       emitpcode(POC_MOVLW, popGetLit(0x00));
6200       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6201       emitpcode(POC_MOVLW, popGetLit(0xfe));
6202       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),6,0));
6203       emitpcode(POC_IORLW, popGetLit(0x01));
6204       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6205     } else {
6206       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6207       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6208       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6209       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6210       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6211     }
6212     break;
6213
6214   case 7:
6215     if(same) {
6216       emitpcode(POC_MOVLW, popGetLit(0x00));
6217       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6218       emitpcode(POC_MOVLW, popGetLit(0xff));
6219       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6220     } else {
6221       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6222       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6223       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6224     }
6225
6226   default:
6227     break;
6228   }
6229 }
6230
6231 /*-----------------------------------------------------------------*/
6232 /* shiftR1Left2Result - shift right one byte from left to result   */
6233 /*-----------------------------------------------------------------*/
6234 static void shiftR1Left2Result (operand *left, int offl,
6235                                 operand *result, int offr,
6236                                 int shCount, int sign)
6237 {
6238   int same;
6239
6240   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6241
6242   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6243
6244   /* Copy the msb into the carry if signed. */
6245   if(sign) {
6246     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6247     return;
6248   }
6249
6250
6251
6252   switch(shCount) {
6253   case 1:
6254     emitCLRC;
6255     if(same) 
6256       emitpcode(POC_RRF, popGet(AOP(result),offr));
6257     else {
6258       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6259       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6260     }
6261     break;
6262   case 2:
6263     emitCLRC;
6264     if(same) {
6265       emitpcode(POC_RRF, popGet(AOP(result),offr));
6266     } else {
6267       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6268       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6269     }
6270     emitCLRC;
6271     emitpcode(POC_RRF, popGet(AOP(result),offr));
6272
6273     break;
6274   case 3:
6275     if(same)
6276       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6277     else {
6278       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6279       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6280     }
6281
6282     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6283     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6284     emitpcode(POC_ANDLW, popGetLit(0x1f));
6285     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6286     break;
6287       
6288   case 4:
6289     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6290     emitpcode(POC_ANDLW, popGetLit(0x0f));
6291     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6292     break;
6293
6294   case 5:
6295     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6296     emitpcode(POC_ANDLW, popGetLit(0x0f));
6297     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6298     emitCLRC;
6299     emitpcode(POC_RRF, popGet(AOP(result),offr));
6300
6301     break;
6302   case 6:
6303
6304     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6305     emitpcode(POC_ANDLW, popGetLit(0x80));
6306     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6307     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6308     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6309     break;
6310
6311   case 7:
6312
6313     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6314     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6315     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6316
6317     break;
6318
6319   default:
6320     break;
6321   }
6322 }
6323
6324 /*-----------------------------------------------------------------*/
6325 /* shiftL1Left2Result - shift left one byte from left to result    */
6326 /*-----------------------------------------------------------------*/
6327 static void shiftL1Left2Result (operand *left, int offl,
6328                                 operand *result, int offr, int shCount)
6329 {
6330   int same;
6331
6332   //    char *l;
6333   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6334
6335   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6336   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6337     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6338     //    MOVA(l);
6339     /* shift left accumulator */
6340     //AccLsh(shCount); // don't comment out just yet...
6341   //    aopPut(AOP(result),"a",offr);
6342
6343   switch(shCount) {
6344   case 1:
6345     /* Shift left 1 bit position */
6346     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6347     if(same) {
6348       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6349     } else {
6350       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6351       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6352     }
6353     break;
6354   case 2:
6355     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6356     emitpcode(POC_ANDLW,popGetLit(0x7e));
6357     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6358     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6359     break;
6360   case 3:
6361     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6362     emitpcode(POC_ANDLW,popGetLit(0x3e));
6363     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6364     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6365     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6366     break;
6367   case 4:
6368     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6369     emitpcode(POC_ANDLW, popGetLit(0xf0));
6370     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6371     break;
6372   case 5:
6373     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6374     emitpcode(POC_ANDLW, popGetLit(0xf0));
6375     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6376     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6377     break;
6378   case 6:
6379     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6380     emitpcode(POC_ANDLW, popGetLit(0x30));
6381     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6382     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6383     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6384     break;
6385   case 7:
6386     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6387     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6388     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6389     break;
6390
6391   default:
6392     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6393   }
6394
6395 }
6396
6397 /*-----------------------------------------------------------------*/
6398 /* movLeft2Result - move byte from left to result                  */
6399 /*-----------------------------------------------------------------*/
6400 static void movLeft2Result (operand *left, int offl,
6401                             operand *result, int offr, int sign)
6402 {
6403   char *l;
6404   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6405   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6406     l = aopGet(AOP(left),offl,FALSE,FALSE);
6407
6408     if (*l == '@' && (IS_AOP_PREG(result))) {
6409       pic14_emitcode("mov","a,%s",l);
6410       aopPut(AOP(result),"a",offr);
6411     } else {
6412       //if(!sign) {
6413       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6414       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6415
6416       //aopPut(AOP(result),l,offr);
6417       //}else{
6418       /* MSB sign in acc.7 ! */
6419       //if(pic14_getDataSize(left) == offl+1){
6420       //  pic14_emitcode("mov","a,%s",l);
6421       //  aopPut(AOP(result),"a",offr);
6422       //}
6423       //}
6424     }
6425   }
6426 }
6427
6428 /*-----------------------------------------------------------------*/
6429 /* shiftL2Left2Result - shift left two bytes from left to result   */
6430 /*-----------------------------------------------------------------*/
6431 static void shiftL2Left2Result (operand *left, int offl,
6432                                 operand *result, int offr, int shCount)
6433 {
6434
6435
6436   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6437
6438   if(pic14_sameRegs(AOP(result), AOP(left))) {
6439     switch(shCount) {
6440     case 0:
6441       break;
6442     case 1:
6443     case 2:
6444     case 3:
6445
6446       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6447       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6448       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6449
6450       while(--shCount) {
6451         emitCLRC;
6452         emitpcode(POC_RLF, popGet(AOP(result),offr));
6453         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6454       }
6455
6456       break;
6457     case 4:
6458     case 5:
6459       emitpcode(POC_MOVLW, popGetLit(0x0f));
6460       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6461       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6462       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6463       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6464       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6465       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6466       if(shCount >=5) {
6467         emitpcode(POC_RLF, popGet(AOP(result),offr));
6468         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6469       }
6470       break;
6471     case 6:
6472       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6473       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6474       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6475       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6476       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6477       emitpcode(POC_ANDLW,popGetLit(0xc0));
6478       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6479       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6480       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6481       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6482       break;
6483     case 7:
6484       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6485       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6486       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6487       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6488       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6489     }
6490
6491   } else {
6492     switch(shCount) {
6493     case 0:
6494       break;
6495     case 1:
6496     case 2:
6497     case 3:
6498       /* note, use a mov/add for the shift since the mov has a
6499          chance of getting optimized out */
6500       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6501       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6502       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6503       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6504       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6505
6506       while(--shCount) {
6507         emitCLRC;
6508         emitpcode(POC_RLF, popGet(AOP(result),offr));
6509         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6510       }
6511       break;
6512
6513     case 4:
6514     case 5:
6515       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6516       emitpcode(POC_ANDLW, popGetLit(0xF0));
6517       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6518       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6519       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6520       emitpcode(POC_ANDLW, popGetLit(0xF0));
6521       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6522       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6523
6524
6525       if(shCount == 5) {
6526         emitpcode(POC_RLF, popGet(AOP(result),offr));
6527         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6528       }
6529       break;
6530     case 6:
6531       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6532       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6533       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6534       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6535
6536       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6537       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6538       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6539       emitpcode(POC_ANDLW,popGetLit(0xc0));
6540       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6541       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6542       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6543       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6544       break;
6545     case 7:
6546       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6547       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6548       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6549       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6550       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6551     }
6552   }
6553
6554 }
6555 /*-----------------------------------------------------------------*/
6556 /* shiftR2Left2Result - shift right two bytes from left to result  */
6557 /*-----------------------------------------------------------------*/
6558 static void shiftR2Left2Result (operand *left, int offl,
6559                                 operand *result, int offr,
6560                                 int shCount, int sign)
6561 {
6562   int same=0;
6563
6564   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6565   same = pic14_sameRegs(AOP(result), AOP(left));
6566
6567   if(same && ((offl + MSB16) == offr)){
6568     same=1;
6569     /* don't crash result[offr] */
6570     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6571     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6572   } else {
6573     movLeft2Result(left,offl, result, offr, 0);
6574     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6575   }
6576   /* a:x >> shCount (x = lsb(result))*/
6577 /*
6578   if(sign)
6579     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6580   else {
6581     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6582 */
6583   switch(shCount) {
6584   case 0:
6585     break;
6586   case 1:
6587   case 2:
6588   case 3:
6589     emitCLRC;
6590     if(same) {
6591       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6592       emitpcode(POC_RRF,popGet(AOP(result),offr));
6593     } else {
6594
6595       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6596       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6597       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6598       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6599     }
6600
6601     while(--shCount) {
6602       emitCLRC;
6603       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6604       emitpcode(POC_RRF,popGet(AOP(result),offr));
6605     }
6606     break;
6607   case 4:
6608   case 5:
6609     if(same) {
6610
6611       emitpcode(POC_MOVLW, popGetLit(0xf0));
6612       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6613       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6614
6615       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6616       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6617       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6618       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6619     } else {
6620       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6621       emitpcode(POC_ANDLW, popGetLit(0x0f));
6622       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6623
6624       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6625       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6626       emitpcode(POC_ANDLW, popGetLit(0xf0));
6627       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6628       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6629     }
6630
6631     if(shCount >=5) {
6632       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6633       emitpcode(POC_RRF, popGet(AOP(result),offr));
6634     }
6635
6636     break;
6637
6638   case 6:
6639     if(same) {
6640
6641       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6642       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6643
6644       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6645       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6646       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6647       emitpcode(POC_ANDLW,popGetLit(0x03));
6648       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6649       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6650       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6651       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6652     } else {
6653       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6654       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6655       emitpcode(POC_RLFW, popGet(AOP(result),offl+MSB16));
6656       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6657       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6658       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6659       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6660       emitpcode(POC_ANDLW,popGetLit(0x03));
6661       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6662     }
6663
6664     break;
6665   case 7:
6666     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6667     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6668     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6669     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6670     emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6671   }
6672 }
6673
6674
6675 /*-----------------------------------------------------------------*/
6676 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6677 /*-----------------------------------------------------------------*/
6678 static void shiftLLeftOrResult (operand *left, int offl,
6679                                 operand *result, int offr, int shCount)
6680 {
6681     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6682     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6683     /* shift left accumulator */
6684     AccLsh(shCount);
6685     /* or with result */
6686     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6687     /* back to result */
6688     aopPut(AOP(result),"a",offr);
6689 }
6690
6691 /*-----------------------------------------------------------------*/
6692 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6693 /*-----------------------------------------------------------------*/
6694 static void shiftRLeftOrResult (operand *left, int offl,
6695                                 operand *result, int offr, int shCount)
6696 {
6697     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6698     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6699     /* shift right accumulator */
6700     AccRsh(shCount);
6701     /* or with result */
6702     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6703     /* back to result */
6704     aopPut(AOP(result),"a",offr);
6705 }
6706
6707 /*-----------------------------------------------------------------*/
6708 /* genlshOne - left shift a one byte quantity by known count       */
6709 /*-----------------------------------------------------------------*/
6710 static void genlshOne (operand *result, operand *left, int shCount)
6711 {       
6712     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6713     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6714 }
6715
6716 /*-----------------------------------------------------------------*/
6717 /* genlshTwo - left shift two bytes by known amount != 0           */
6718 /*-----------------------------------------------------------------*/
6719 static void genlshTwo (operand *result,operand *left, int shCount)
6720 {
6721     int size;
6722     
6723     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6724     size = pic14_getDataSize(result);
6725
6726     /* if shCount >= 8 */
6727     if (shCount >= 8) {
6728         shCount -= 8 ;
6729
6730         if (size > 1){
6731             if (shCount)
6732                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6733             else 
6734                 movLeft2Result(left, LSB, result, MSB16, 0);
6735         }
6736         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6737     }
6738
6739     /*  1 <= shCount <= 7 */
6740     else {  
6741         if(size == 1)
6742             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6743         else 
6744             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6745     }
6746 }
6747
6748 /*-----------------------------------------------------------------*/
6749 /* shiftLLong - shift left one long from left to result            */
6750 /* offl = LSB or MSB16                                             */
6751 /*-----------------------------------------------------------------*/
6752 static void shiftLLong (operand *left, operand *result, int offr )
6753 {
6754     char *l;
6755     int size = AOP_SIZE(result);
6756
6757     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6758     if(size >= LSB+offr){
6759         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6760         MOVA(l);
6761         pic14_emitcode("add","a,acc");
6762         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6763             size >= MSB16+offr && offr != LSB )
6764             pic14_emitcode("xch","a,%s",
6765                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6766         else        
6767             aopPut(AOP(result),"a",LSB+offr);
6768     }
6769
6770     if(size >= MSB16+offr){
6771         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6772             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6773             MOVA(l);
6774         }
6775         pic14_emitcode("rlc","a");
6776         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6777             size >= MSB24+offr && offr != LSB)
6778             pic14_emitcode("xch","a,%s",
6779                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6780         else        
6781             aopPut(AOP(result),"a",MSB16+offr);
6782     }
6783
6784     if(size >= MSB24+offr){
6785         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6786             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6787             MOVA(l);
6788         }
6789         pic14_emitcode("rlc","a");
6790         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6791             size >= MSB32+offr && offr != LSB )
6792             pic14_emitcode("xch","a,%s",
6793                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6794         else        
6795             aopPut(AOP(result),"a",MSB24+offr);
6796     }
6797
6798     if(size > MSB32+offr){
6799         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6800             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6801             MOVA(l);    
6802         }
6803         pic14_emitcode("rlc","a");
6804         aopPut(AOP(result),"a",MSB32+offr);
6805     }
6806     if(offr != LSB)
6807         aopPut(AOP(result),zero,LSB);       
6808 }
6809
6810 /*-----------------------------------------------------------------*/
6811 /* genlshFour - shift four byte by a known amount != 0             */
6812 /*-----------------------------------------------------------------*/
6813 static void genlshFour (operand *result, operand *left, int shCount)
6814 {
6815     int size;
6816
6817     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6818     size = AOP_SIZE(result);
6819
6820     /* if shifting more that 3 bytes */
6821     if (shCount >= 24 ) {
6822         shCount -= 24;
6823         if (shCount)
6824             /* lowest order of left goes to the highest
6825             order of the destination */
6826             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6827         else
6828             movLeft2Result(left, LSB, result, MSB32, 0);
6829         aopPut(AOP(result),zero,LSB);
6830         aopPut(AOP(result),zero,MSB16);
6831         aopPut(AOP(result),zero,MSB32);
6832         return;
6833     }
6834
6835     /* more than two bytes */
6836     else if ( shCount >= 16 ) {
6837         /* lower order two bytes goes to higher order two bytes */
6838         shCount -= 16;
6839         /* if some more remaining */
6840         if (shCount)
6841             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6842         else {
6843             movLeft2Result(left, MSB16, result, MSB32, 0);
6844             movLeft2Result(left, LSB, result, MSB24, 0);
6845         }
6846         aopPut(AOP(result),zero,MSB16);
6847         aopPut(AOP(result),zero,LSB);
6848         return;
6849     }    
6850
6851     /* if more than 1 byte */
6852     else if ( shCount >= 8 ) {
6853         /* lower order three bytes goes to higher order  three bytes */
6854         shCount -= 8;
6855         if(size == 2){
6856             if(shCount)
6857                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6858             else
6859                 movLeft2Result(left, LSB, result, MSB16, 0);
6860         }
6861         else{   /* size = 4 */
6862             if(shCount == 0){
6863                 movLeft2Result(left, MSB24, result, MSB32, 0);
6864                 movLeft2Result(left, MSB16, result, MSB24, 0);
6865                 movLeft2Result(left, LSB, result, MSB16, 0);
6866                 aopPut(AOP(result),zero,LSB);
6867             }
6868             else if(shCount == 1)
6869                 shiftLLong(left, result, MSB16);
6870             else{
6871                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6872                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6873                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6874                 aopPut(AOP(result),zero,LSB);
6875             }
6876         }
6877     }
6878
6879     /* 1 <= shCount <= 7 */
6880     else if(shCount <= 2){
6881         shiftLLong(left, result, LSB);
6882         if(shCount == 2)
6883             shiftLLong(result, result, LSB);
6884     }
6885     /* 3 <= shCount <= 7, optimize */
6886     else{
6887         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6888         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6889         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6890     }
6891 }
6892
6893 /*-----------------------------------------------------------------*/
6894 /* genLeftShiftLiteral - left shifting by known count              */
6895 /*-----------------------------------------------------------------*/
6896 static void genLeftShiftLiteral (operand *left,
6897                                  operand *right,
6898                                  operand *result,
6899                                  iCode *ic)
6900 {    
6901     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6902     int size;
6903
6904     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6905     freeAsmop(right,NULL,ic,TRUE);
6906
6907     aopOp(left,ic,FALSE);
6908     aopOp(result,ic,FALSE);
6909
6910     size = getSize(operandType(result));
6911
6912 #if VIEW_SIZE
6913     pic14_emitcode("; shift left ","result %d, left %d",size,
6914              AOP_SIZE(left));
6915 #endif
6916
6917     /* I suppose that the left size >= result size */
6918     if(shCount == 0){
6919         while(size--){
6920             movLeft2Result(left, size, result, size, 0);
6921         }
6922     }
6923
6924     else if(shCount >= (size * 8))
6925         while(size--)
6926             aopPut(AOP(result),zero,size);
6927     else{
6928         switch (size) {
6929             case 1:
6930                 genlshOne (result,left,shCount);
6931                 break;
6932
6933             case 2:
6934             case 3:
6935                 genlshTwo (result,left,shCount);
6936                 break;
6937
6938             case 4:
6939                 genlshFour (result,left,shCount);
6940                 break;
6941         }
6942     }
6943     freeAsmop(left,NULL,ic,TRUE);
6944     freeAsmop(result,NULL,ic,TRUE);
6945 }
6946
6947 /*-----------------------------------------------------------------*
6948  * genMultiAsm - repeat assembly instruction for size of register.
6949  * if endian == 1, then the high byte (i.e base address + size of 
6950  * register) is used first else the low byte is used first;
6951  *-----------------------------------------------------------------*/
6952 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
6953 {
6954
6955   int offset = 0;
6956
6957   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6958
6959   if(!reg)
6960     return;
6961
6962   if(!endian) {
6963     endian = 1;
6964   } else {
6965     endian = -1;
6966     offset = size-1;
6967   }
6968
6969   while(size--) {
6970     emitpcode(poc,    popGet(AOP(reg),offset));
6971     offset += endian;
6972   }
6973
6974 }
6975 /*-----------------------------------------------------------------*/
6976 /* genLeftShift - generates code for left shifting                 */
6977 /*-----------------------------------------------------------------*/
6978 static void genLeftShift (iCode *ic)
6979 {
6980     operand *left,*right, *result;
6981     int size, offset;
6982     char *l;
6983     symbol *tlbl , *tlbl1;
6984
6985     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6986
6987     right = IC_RIGHT(ic);
6988     left  = IC_LEFT(ic);
6989     result = IC_RESULT(ic);
6990
6991     aopOp(right,ic,FALSE);
6992
6993     /* if the shift count is known then do it 
6994     as efficiently as possible */
6995     if (AOP_TYPE(right) == AOP_LIT) {
6996         genLeftShiftLiteral (left,right,result,ic);
6997         return ;
6998     }
6999
7000     /* shift count is unknown then we have to form 
7001     a loop get the loop count in B : Note: we take
7002     only the lower order byte since shifting
7003     more that 32 bits make no sense anyway, ( the
7004     largest size of an object can be only 32 bits ) */  
7005
7006     
7007     aopOp(left,ic,FALSE);
7008     aopOp(result,ic,FALSE);
7009
7010     /* now move the left to the result if they are not the
7011     same */
7012     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7013         AOP_SIZE(result) > 1) {
7014
7015         size = AOP_SIZE(result);
7016         offset=0;
7017         while (size--) {
7018             l = aopGet(AOP(left),offset,FALSE,TRUE);
7019             if (*l == '@' && (IS_AOP_PREG(result))) {
7020
7021                 pic14_emitcode("mov","a,%s",l);
7022                 aopPut(AOP(result),"a",offset);
7023             } else
7024                 aopPut(AOP(result),l,offset);
7025             offset++;
7026         }
7027     }
7028
7029     size = AOP_SIZE(result);
7030
7031     /* if it is only one byte then */
7032     if (size == 1) {
7033       if(optimized_for_speed) {
7034         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7035         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7036         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7037         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7038         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7039         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7040         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7041         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7042         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7043         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7044         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7045         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7046       } else {
7047
7048         tlbl = newiTempLabel(NULL);
7049         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7050           emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7051           emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7052         }
7053
7054         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7055         emitpcode(POC_RRF,    popGet(AOP(result),0));
7056         emitpLabel(tlbl->key);
7057         emitpcode(POC_RLF,    popGet(AOP(result),0));
7058         emitpcode(POC_ADDLW,  popGetLit(1));
7059         emitSKPC;
7060         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7061       }
7062       goto release ;
7063     }
7064     
7065     if (pic14_sameRegs(AOP(left),AOP(result))) {
7066
7067       tlbl = newiTempLabel(NULL);
7068       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7069       genMultiAsm(POC_RRF, result, size,1);
7070       emitpLabel(tlbl->key);
7071       genMultiAsm(POC_RLF, result, size,0);
7072       emitpcode(POC_ADDLW,  popGetLit(1));
7073       emitSKPC;
7074       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7075       goto release;
7076     }
7077
7078     tlbl = newiTempLabel(NULL);
7079     offset = 0 ;   
7080     tlbl1 = newiTempLabel(NULL);
7081
7082     reAdjustPreg(AOP(result));    
7083     
7084     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7085     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7086     l = aopGet(AOP(result),offset,FALSE,FALSE);
7087     MOVA(l);
7088     pic14_emitcode("add","a,acc");         
7089     aopPut(AOP(result),"a",offset++);
7090     while (--size) {
7091         l = aopGet(AOP(result),offset,FALSE,FALSE);
7092         MOVA(l);
7093         pic14_emitcode("rlc","a");         
7094         aopPut(AOP(result),"a",offset++);
7095     }
7096     reAdjustPreg(AOP(result));
7097
7098     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7099     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7100 release:
7101     freeAsmop (right,NULL,ic,TRUE);
7102     freeAsmop(left,NULL,ic,TRUE);
7103     freeAsmop(result,NULL,ic,TRUE);
7104 }
7105
7106 /*-----------------------------------------------------------------*/
7107 /* genrshOne - right shift a one byte quantity by known count      */
7108 /*-----------------------------------------------------------------*/
7109 static void genrshOne (operand *result, operand *left,
7110                        int shCount, int sign)
7111 {
7112     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7113     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7114 }
7115
7116 /*-----------------------------------------------------------------*/
7117 /* genrshTwo - right shift two bytes by known amount != 0          */
7118 /*-----------------------------------------------------------------*/
7119 static void genrshTwo (operand *result,operand *left,
7120                        int shCount, int sign)
7121 {
7122   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7123   /* if shCount >= 8 */
7124   if (shCount >= 8) {
7125     shCount -= 8 ;
7126     if (shCount)
7127       shiftR1Left2Result(left, MSB16, result, LSB,
7128                          shCount, sign);
7129     else
7130       movLeft2Result(left, MSB16, result, LSB, sign);
7131
7132     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7133
7134     if(sign) {
7135       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7136       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7137     }
7138   }
7139
7140   /*  1 <= shCount <= 7 */
7141   else
7142     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7143 }
7144
7145 /*-----------------------------------------------------------------*/
7146 /* shiftRLong - shift right one long from left to result           */
7147 /* offl = LSB or MSB16                                             */
7148 /*-----------------------------------------------------------------*/
7149 static void shiftRLong (operand *left, int offl,
7150                         operand *result, int sign)
7151 {
7152     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7153     if(!sign)
7154         pic14_emitcode("clr","c");
7155     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7156     if(sign)
7157         pic14_emitcode("mov","c,acc.7");
7158     pic14_emitcode("rrc","a");
7159     aopPut(AOP(result),"a",MSB32-offl);
7160     if(offl == MSB16)
7161         /* add sign of "a" */
7162         addSign(result, MSB32, sign);
7163
7164     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7165     pic14_emitcode("rrc","a");
7166     aopPut(AOP(result),"a",MSB24-offl);
7167
7168     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7169     pic14_emitcode("rrc","a");
7170     aopPut(AOP(result),"a",MSB16-offl);
7171
7172     if(offl == LSB){
7173         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7174         pic14_emitcode("rrc","a");
7175         aopPut(AOP(result),"a",LSB);
7176     }
7177 }
7178
7179 /*-----------------------------------------------------------------*/
7180 /* genrshFour - shift four byte by a known amount != 0             */
7181 /*-----------------------------------------------------------------*/
7182 static void genrshFour (operand *result, operand *left,
7183                         int shCount, int sign)
7184 {
7185     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7186     /* if shifting more that 3 bytes */
7187     if(shCount >= 24 ) {
7188         shCount -= 24;
7189         if(shCount)
7190             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7191         else
7192             movLeft2Result(left, MSB32, result, LSB, sign);
7193         addSign(result, MSB16, sign);
7194     }
7195     else if(shCount >= 16){
7196         shCount -= 16;
7197         if(shCount)
7198             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7199         else{
7200             movLeft2Result(left, MSB24, result, LSB, 0);
7201             movLeft2Result(left, MSB32, result, MSB16, sign);
7202         }
7203         addSign(result, MSB24, sign);
7204     }
7205     else if(shCount >= 8){
7206         shCount -= 8;
7207         if(shCount == 1)
7208             shiftRLong(left, MSB16, result, sign);
7209         else if(shCount == 0){
7210             movLeft2Result(left, MSB16, result, LSB, 0);
7211             movLeft2Result(left, MSB24, result, MSB16, 0);
7212             movLeft2Result(left, MSB32, result, MSB24, sign);
7213             addSign(result, MSB32, sign);
7214         }
7215         else{
7216             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7217             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7218             /* the last shift is signed */
7219             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7220             addSign(result, MSB32, sign);
7221         }
7222     }
7223     else{   /* 1 <= shCount <= 7 */
7224         if(shCount <= 2){
7225             shiftRLong(left, LSB, result, sign);
7226             if(shCount == 2)
7227                 shiftRLong(result, LSB, result, sign);
7228         }
7229         else{
7230             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7231             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7232             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7233         }
7234     }
7235 }
7236
7237 /*-----------------------------------------------------------------*/
7238 /* genRightShiftLiteral - right shifting by known count            */
7239 /*-----------------------------------------------------------------*/
7240 static void genRightShiftLiteral (operand *left,
7241                                   operand *right,
7242                                   operand *result,
7243                                   iCode *ic,
7244                                   int sign)
7245 {    
7246     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7247     int size;
7248
7249     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7250     freeAsmop(right,NULL,ic,TRUE);
7251
7252     aopOp(left,ic,FALSE);
7253     aopOp(result,ic,FALSE);
7254
7255 #if VIEW_SIZE
7256     pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7257              AOP_SIZE(left));
7258 #endif
7259
7260     size = pic14_getDataSize(left);
7261     /* test the LEFT size !!! */
7262
7263     /* I suppose that the left size >= result size */
7264     if(shCount == 0){
7265         size = pic14_getDataSize(result);
7266         while(size--)
7267             movLeft2Result(left, size, result, size, 0);
7268     }
7269
7270     else if(shCount >= (size * 8)){
7271         if(sign)
7272             /* get sign in acc.7 */
7273             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
7274         addSign(result, LSB, sign);
7275     } else{
7276         switch (size) {
7277             case 1:
7278                 genrshOne (result,left,shCount,sign);
7279                 break;
7280
7281             case 2:
7282                 genrshTwo (result,left,shCount,sign);
7283                 break;
7284
7285             case 4:
7286                 genrshFour (result,left,shCount,sign);
7287                 break;
7288             default :
7289                 break;
7290         }
7291
7292         freeAsmop(left,NULL,ic,TRUE);
7293         freeAsmop(result,NULL,ic,TRUE);
7294     }
7295 }
7296
7297 /*-----------------------------------------------------------------*/
7298 /* genSignedRightShift - right shift of signed number              */
7299 /*-----------------------------------------------------------------*/
7300 static void genSignedRightShift (iCode *ic)
7301 {
7302   operand *right, *left, *result;
7303   int size, offset;
7304   //  char *l;
7305   symbol *tlbl, *tlbl1 ;
7306   pCodeOp *pctemp;
7307
7308   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7309
7310   /* we do it the hard way put the shift count in b
7311      and loop thru preserving the sign */
7312   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7313
7314   right = IC_RIGHT(ic);
7315   left  = IC_LEFT(ic);
7316   result = IC_RESULT(ic);
7317
7318   aopOp(right,ic,FALSE);  
7319   aopOp(left,ic,FALSE);
7320   aopOp(result,ic,FALSE);
7321
7322
7323   if ( AOP_TYPE(right) == AOP_LIT) {
7324     genRightShiftLiteral (left,right,result,ic,1);
7325     return ;
7326   }
7327   /* shift count is unknown then we have to form 
7328      a loop get the loop count in B : Note: we take
7329      only the lower order byte since shifting
7330      more that 32 bits make no sense anyway, ( the
7331      largest size of an object can be only 32 bits ) */  
7332
7333   //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7334   //pic14_emitcode("inc","b");
7335   //freeAsmop (right,NULL,ic,TRUE);
7336   //aopOp(left,ic,FALSE);
7337   //aopOp(result,ic,FALSE);
7338
7339   /* now move the left to the result if they are not the
7340      same */
7341   if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7342       AOP_SIZE(result) > 1) {
7343
7344     size = AOP_SIZE(result);
7345     offset=0;
7346     while (size--) { 
7347       /*
7348         l = aopGet(AOP(left),offset,FALSE,TRUE);
7349         if (*l == '@' && IS_AOP_PREG(result)) {
7350
7351         pic14_emitcode("mov","a,%s",l);
7352         aopPut(AOP(result),"a",offset);
7353         } else
7354         aopPut(AOP(result),l,offset);
7355       */
7356       emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7357       emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7358
7359       offset++;
7360     }
7361   }
7362
7363   /* mov the highest order bit to OVR */    
7364   tlbl = newiTempLabel(NULL);
7365   tlbl1= newiTempLabel(NULL);
7366
7367   size = AOP_SIZE(result);
7368   offset = size - 1;
7369
7370   pctemp = popGetTempReg();  /* grab a temporary working register. */
7371
7372   emitpcode(POC_MOVFW, popGet(AOP(right),0));
7373
7374   /* offset should be 0, 1 or 3 */
7375   emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7376   emitSKPNZ;
7377   emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7378
7379   emitpcode(POC_MOVWF, pctemp);
7380
7381
7382   emitpLabel(tlbl->key);
7383
7384   emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7385   emitpcode(POC_RRF,   popGet(AOP(result),offset));
7386
7387   while(--size) {
7388     emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7389   }
7390
7391   emitpcode(POC_DECFSZ,  pctemp);
7392   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7393   emitpLabel(tlbl1->key);
7394
7395   popReleaseTempReg(pctemp);
7396 #if 0
7397   size = AOP_SIZE(result);
7398   offset = size - 1;
7399   pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7400   pic14_emitcode("rlc","a");
7401   pic14_emitcode("mov","ov,c");
7402   /* if it is only one byte then */
7403   if (size == 1) {
7404     l = aopGet(AOP(left),0,FALSE,FALSE);
7405     MOVA(l);
7406     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7407     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7408     pic14_emitcode("mov","c,ov");
7409     pic14_emitcode("rrc","a");
7410     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7411     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7412     aopPut(AOP(result),"a",0);
7413     goto release ;
7414   }
7415
7416   reAdjustPreg(AOP(result));
7417   pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7418   pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7419   pic14_emitcode("mov","c,ov");
7420   while (size--) {
7421     l = aopGet(AOP(result),offset,FALSE,FALSE);
7422     MOVA(l);
7423     pic14_emitcode("rrc","a");         
7424     aopPut(AOP(result),"a",offset--);
7425   }
7426   reAdjustPreg(AOP(result));
7427   pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7428   pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7429
7430  release:
7431 #endif
7432
7433   freeAsmop(left,NULL,ic,TRUE);
7434   freeAsmop(result,NULL,ic,TRUE);
7435   freeAsmop(right,NULL,ic,TRUE);
7436 }
7437
7438 /*-----------------------------------------------------------------*/
7439 /* genRightShift - generate code for right shifting                */
7440 /*-----------------------------------------------------------------*/
7441 static void genRightShift (iCode *ic)
7442 {
7443     operand *right, *left, *result;
7444     sym_link *retype ;
7445     int size, offset;
7446     char *l;
7447     symbol *tlbl, *tlbl1 ;
7448
7449     /* if signed then we do it the hard way preserve the
7450     sign bit moving it inwards */
7451     retype = getSpec(operandType(IC_RESULT(ic)));
7452     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7453
7454     if (!SPEC_USIGN(retype)) {
7455         genSignedRightShift (ic);
7456         return ;
7457     }
7458
7459     /* signed & unsigned types are treated the same : i.e. the
7460     signed is NOT propagated inwards : quoting from the
7461     ANSI - standard : "for E1 >> E2, is equivalent to division
7462     by 2**E2 if unsigned or if it has a non-negative value,
7463     otherwise the result is implementation defined ", MY definition
7464     is that the sign does not get propagated */
7465
7466     right = IC_RIGHT(ic);
7467     left  = IC_LEFT(ic);
7468     result = IC_RESULT(ic);
7469
7470     aopOp(right,ic,FALSE);
7471
7472     /* if the shift count is known then do it 
7473     as efficiently as possible */
7474     if (AOP_TYPE(right) == AOP_LIT) {
7475         genRightShiftLiteral (left,right,result,ic, 0);
7476         return ;
7477     }
7478
7479     /* shift count is unknown then we have to form 
7480     a loop get the loop count in B : Note: we take
7481     only the lower order byte since shifting
7482     more that 32 bits make no sense anyway, ( the
7483     largest size of an object can be only 32 bits ) */  
7484
7485     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7486     pic14_emitcode("inc","b");
7487     aopOp(left,ic,FALSE);
7488     aopOp(result,ic,FALSE);
7489
7490     /* now move the left to the result if they are not the
7491     same */
7492     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7493         AOP_SIZE(result) > 1) {
7494
7495         size = AOP_SIZE(result);
7496         offset=0;
7497         while (size--) {
7498             l = aopGet(AOP(left),offset,FALSE,TRUE);
7499             if (*l == '@' && IS_AOP_PREG(result)) {
7500
7501                 pic14_emitcode("mov","a,%s",l);
7502                 aopPut(AOP(result),"a",offset);
7503             } else
7504                 aopPut(AOP(result),l,offset);
7505             offset++;
7506         }
7507     }
7508
7509     tlbl = newiTempLabel(NULL);
7510     tlbl1= newiTempLabel(NULL);
7511     size = AOP_SIZE(result);
7512     offset = size - 1;
7513
7514     /* if it is only one byte then */
7515     if (size == 1) {
7516
7517       tlbl = newiTempLabel(NULL);
7518       if (!pic14_sameRegs(AOP(left),AOP(result))) {
7519         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7520         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7521       }
7522
7523       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7524       emitpcode(POC_RLF,    popGet(AOP(result),0));
7525       emitpLabel(tlbl->key);
7526       emitpcode(POC_RRF,    popGet(AOP(result),0));
7527       emitpcode(POC_ADDLW,  popGetLit(1));
7528       emitSKPC;
7529       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7530
7531       goto release ;
7532     }
7533
7534     reAdjustPreg(AOP(result));
7535     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7536     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7537     CLRC;
7538     while (size--) {
7539         l = aopGet(AOP(result),offset,FALSE,FALSE);
7540         MOVA(l);
7541         pic14_emitcode("rrc","a");         
7542         aopPut(AOP(result),"a",offset--);
7543     }
7544     reAdjustPreg(AOP(result));
7545
7546     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7547     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7548
7549 release:
7550     freeAsmop(left,NULL,ic,TRUE);
7551     freeAsmop (right,NULL,ic,TRUE);
7552     freeAsmop(result,NULL,ic,TRUE);
7553 }
7554
7555 /*-----------------------------------------------------------------*/
7556 /* genUnpackBits - generates code for unpacking bits               */
7557 /*-----------------------------------------------------------------*/
7558 static void genUnpackBits (operand *result, char *rname, int ptype)
7559 {    
7560     int shCnt ;
7561     int rlen = 0 ;
7562     sym_link *etype;
7563     int offset = 0 ;
7564
7565     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7566     etype = getSpec(operandType(result));
7567
7568     /* read the first byte  */
7569     switch (ptype) {
7570
7571     case POINTER:
7572     case IPOINTER:
7573         pic14_emitcode("mov","a,@%s",rname);
7574         break;
7575         
7576     case PPOINTER:
7577         pic14_emitcode("movx","a,@%s",rname);
7578         break;
7579         
7580     case FPOINTER:
7581         pic14_emitcode("movx","a,@dptr");
7582         break;
7583
7584     case CPOINTER:
7585         pic14_emitcode("clr","a");
7586         pic14_emitcode("movc","a","@a+dptr");
7587         break;
7588
7589     case GPOINTER:
7590         pic14_emitcode("lcall","__gptrget");
7591         break;
7592     }
7593
7594     /* if we have bitdisplacement then it fits   */
7595     /* into this byte completely or if length is */
7596     /* less than a byte                          */
7597     if ((shCnt = SPEC_BSTR(etype)) || 
7598         (SPEC_BLEN(etype) <= 8))  {
7599
7600         /* shift right acc */
7601         AccRsh(shCnt);
7602
7603         pic14_emitcode("anl","a,#0x%02x",
7604                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7605         aopPut(AOP(result),"a",offset);
7606         return ;
7607     }
7608
7609     /* bit field did not fit in a byte  */
7610     rlen = SPEC_BLEN(etype) - 8;
7611     aopPut(AOP(result),"a",offset++);
7612
7613     while (1)  {
7614
7615         switch (ptype) {
7616         case POINTER:
7617         case IPOINTER:
7618             pic14_emitcode("inc","%s",rname);
7619             pic14_emitcode("mov","a,@%s",rname);
7620             break;
7621             
7622         case PPOINTER:
7623             pic14_emitcode("inc","%s",rname);
7624             pic14_emitcode("movx","a,@%s",rname);
7625             break;
7626
7627         case FPOINTER:
7628             pic14_emitcode("inc","dptr");
7629             pic14_emitcode("movx","a,@dptr");
7630             break;
7631             
7632         case CPOINTER:
7633             pic14_emitcode("clr","a");
7634             pic14_emitcode("inc","dptr");
7635             pic14_emitcode("movc","a","@a+dptr");
7636             break;
7637             
7638         case GPOINTER:
7639             pic14_emitcode("inc","dptr");
7640             pic14_emitcode("lcall","__gptrget");
7641             break;
7642         }
7643
7644         rlen -= 8;            
7645         /* if we are done */
7646         if ( rlen <= 0 )
7647             break ;
7648         
7649         aopPut(AOP(result),"a",offset++);
7650                               
7651     }
7652     
7653     if (rlen) {
7654         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7655         aopPut(AOP(result),"a",offset);        
7656     }
7657     
7658     return ;
7659 }
7660
7661
7662 /*-----------------------------------------------------------------*/
7663 /* genDataPointerGet - generates code when ptr offset is known     */
7664 /*-----------------------------------------------------------------*/
7665 static void genDataPointerGet (operand *left, 
7666                                operand *result, 
7667                                iCode *ic)
7668 {
7669   int size , offset = 0;
7670
7671
7672   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7673
7674
7675   /* optimization - most of the time, left and result are the same
7676    * address, but different types. for the pic code, we could omit
7677    * the following
7678    */
7679
7680   aopOp(result,ic,TRUE);
7681
7682   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7683
7684   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7685
7686   size = AOP_SIZE(result);
7687
7688   while (size--) {
7689     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7690     offset++;
7691   }
7692
7693   freeAsmop(left,NULL,ic,TRUE);
7694   freeAsmop(result,NULL,ic,TRUE);
7695 }
7696
7697 /*-----------------------------------------------------------------*/
7698 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7699 /*-----------------------------------------------------------------*/
7700 static void genNearPointerGet (operand *left, 
7701                                operand *result, 
7702                                iCode *ic)
7703 {
7704     asmop *aop = NULL;
7705     regs *preg = NULL ;
7706     char *rname ;
7707     sym_link *rtype, *retype;
7708     sym_link *ltype = operandType(left);    
7709     char buffer[80];
7710
7711     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7712
7713     rtype = operandType(result);
7714     retype= getSpec(rtype);
7715     
7716     aopOp(left,ic,FALSE);
7717     
7718     /* if left is rematerialisable and
7719        result is not bit variable type and
7720        the left is pointer to data space i.e
7721        lower 128 bytes of space */
7722     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
7723         !IS_BITVAR(retype)         &&
7724         DCL_TYPE(ltype) == POINTER) {
7725       //genDataPointerGet (left,result,ic);
7726         return ;
7727     }
7728     
7729     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7730
7731         /* if the value is already in a pointer register
7732        then don't need anything more */
7733     if (!AOP_INPREG(AOP(left))) {
7734         /* otherwise get a free pointer register */
7735     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7736         aop = newAsmop(0);
7737         preg = getFreePtr(ic,&aop,FALSE);
7738         pic14_emitcode("mov","%s,%s",
7739                 preg->name,
7740                 aopGet(AOP(left),0,FALSE,TRUE));
7741         rname = preg->name ;
7742     } else
7743         rname = aopGet(AOP(left),0,FALSE,FALSE);
7744     
7745     freeAsmop(left,NULL,ic,TRUE);
7746     aopOp (result,ic,FALSE);
7747     
7748       /* if bitfield then unpack the bits */
7749     if (IS_BITVAR(retype)) 
7750         genUnpackBits (result,rname,POINTER);
7751     else {
7752         /* we have can just get the values */
7753         int size = AOP_SIZE(result);
7754         int offset = 0 ;        
7755         
7756     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7757         while (size--) {
7758             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7759
7760                 pic14_emitcode("mov","a,@%s",rname);
7761                 aopPut(AOP(result),"a",offset);
7762             } else {
7763                 sprintf(buffer,"@%s",rname);
7764                 aopPut(AOP(result),buffer,offset);
7765             }
7766             offset++ ;
7767             if (size)
7768                 pic14_emitcode("inc","%s",rname);
7769         }
7770     }
7771
7772     /* now some housekeeping stuff */
7773     if (aop) {
7774         /* we had to allocate for this iCode */
7775     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7776         freeAsmop(NULL,aop,ic,TRUE);
7777     } else { 
7778         /* we did not allocate which means left
7779            already in a pointer register, then
7780            if size > 0 && this could be used again
7781            we have to point it back to where it 
7782            belongs */
7783     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7784         if (AOP_SIZE(result) > 1 &&
7785             !OP_SYMBOL(left)->remat &&
7786             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7787               ic->depth )) {
7788             int size = AOP_SIZE(result) - 1;
7789             while (size--)
7790                 pic14_emitcode("dec","%s",rname);
7791         }
7792     }
7793
7794     /* done */
7795     freeAsmop(result,NULL,ic,TRUE);
7796      
7797 }
7798
7799 /*-----------------------------------------------------------------*/
7800 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
7801 /*-----------------------------------------------------------------*/
7802 static void genPagedPointerGet (operand *left, 
7803                                operand *result, 
7804                                iCode *ic)
7805 {
7806     asmop *aop = NULL;
7807     regs *preg = NULL ;
7808     char *rname ;
7809     sym_link *rtype, *retype;    
7810
7811     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7812
7813     rtype = operandType(result);
7814     retype= getSpec(rtype);
7815     
7816     aopOp(left,ic,FALSE);
7817
7818   /* if the value is already in a pointer register
7819        then don't need anything more */
7820     if (!AOP_INPREG(AOP(left))) {
7821         /* otherwise get a free pointer register */
7822         aop = newAsmop(0);
7823         preg = getFreePtr(ic,&aop,FALSE);
7824         pic14_emitcode("mov","%s,%s",
7825                 preg->name,
7826                 aopGet(AOP(left),0,FALSE,TRUE));
7827         rname = preg->name ;
7828     } else
7829         rname = aopGet(AOP(left),0,FALSE,FALSE);
7830     
7831     freeAsmop(left,NULL,ic,TRUE);
7832     aopOp (result,ic,FALSE);
7833
7834     /* if bitfield then unpack the bits */
7835     if (IS_BITVAR(retype)) 
7836         genUnpackBits (result,rname,PPOINTER);
7837     else {
7838         /* we have can just get the values */
7839         int size = AOP_SIZE(result);
7840         int offset = 0 ;        
7841         
7842         while (size--) {
7843             
7844             pic14_emitcode("movx","a,@%s",rname);
7845             aopPut(AOP(result),"a",offset);
7846             
7847             offset++ ;
7848             
7849             if (size)
7850                 pic14_emitcode("inc","%s",rname);
7851         }
7852     }
7853
7854     /* now some housekeeping stuff */
7855     if (aop) {
7856         /* we had to allocate for this iCode */
7857         freeAsmop(NULL,aop,ic,TRUE);
7858     } else { 
7859         /* we did not allocate which means left
7860            already in a pointer register, then
7861            if size > 0 && this could be used again
7862            we have to point it back to where it 
7863            belongs */
7864         if (AOP_SIZE(result) > 1 &&
7865             !OP_SYMBOL(left)->remat &&
7866             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7867               ic->depth )) {
7868             int size = AOP_SIZE(result) - 1;
7869             while (size--)
7870                 pic14_emitcode("dec","%s",rname);
7871         }
7872     }
7873
7874     /* done */
7875     freeAsmop(result,NULL,ic,TRUE);
7876     
7877         
7878 }
7879
7880 /*-----------------------------------------------------------------*/
7881 /* genFarPointerGet - gget value from far space                    */
7882 /*-----------------------------------------------------------------*/
7883 static void genFarPointerGet (operand *left,
7884                               operand *result, iCode *ic)
7885 {
7886     int size, offset ;
7887     sym_link *retype = getSpec(operandType(result));
7888
7889     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7890
7891     aopOp(left,ic,FALSE);
7892
7893     /* if the operand is already in dptr 
7894     then we do nothing else we move the value to dptr */
7895     if (AOP_TYPE(left) != AOP_STR) {
7896         /* if this is remateriazable */
7897         if (AOP_TYPE(left) == AOP_IMMD)
7898             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7899         else { /* we need to get it byte by byte */
7900             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7901             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7902             if (options.model == MODEL_FLAT24)
7903             {
7904                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7905             }
7906         }
7907     }
7908     /* so dptr know contains the address */
7909     freeAsmop(left,NULL,ic,TRUE);
7910     aopOp(result,ic,FALSE);
7911
7912     /* if bit then unpack */
7913     if (IS_BITVAR(retype)) 
7914         genUnpackBits(result,"dptr",FPOINTER);
7915     else {
7916         size = AOP_SIZE(result);
7917         offset = 0 ;
7918
7919         while (size--) {
7920             pic14_emitcode("movx","a,@dptr");
7921             aopPut(AOP(result),"a",offset++);
7922             if (size)
7923                 pic14_emitcode("inc","dptr");
7924         }
7925     }
7926
7927     freeAsmop(result,NULL,ic,TRUE);
7928 }
7929 #if 0
7930 /*-----------------------------------------------------------------*/
7931 /* genCodePointerGet - get value from code space                  */
7932 /*-----------------------------------------------------------------*/
7933 static void genCodePointerGet (operand *left,
7934                                 operand *result, iCode *ic)
7935 {
7936     int size, offset ;
7937     sym_link *retype = getSpec(operandType(result));
7938
7939     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7940
7941     aopOp(left,ic,FALSE);
7942
7943     /* if the operand is already in dptr 
7944     then we do nothing else we move the value to dptr */
7945     if (AOP_TYPE(left) != AOP_STR) {
7946         /* if this is remateriazable */
7947         if (AOP_TYPE(left) == AOP_IMMD)
7948             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7949         else { /* we need to get it byte by byte */
7950             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7951             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7952             if (options.model == MODEL_FLAT24)
7953             {
7954                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7955             }
7956         }
7957     }
7958     /* so dptr know contains the address */
7959     freeAsmop(left,NULL,ic,TRUE);
7960     aopOp(result,ic,FALSE);
7961
7962     /* if bit then unpack */
7963     if (IS_BITVAR(retype)) 
7964         genUnpackBits(result,"dptr",CPOINTER);
7965     else {
7966         size = AOP_SIZE(result);
7967         offset = 0 ;
7968
7969         while (size--) {
7970             pic14_emitcode("clr","a");
7971             pic14_emitcode("movc","a,@a+dptr");
7972             aopPut(AOP(result),"a",offset++);
7973             if (size)
7974                 pic14_emitcode("inc","dptr");
7975         }
7976     }
7977
7978     freeAsmop(result,NULL,ic,TRUE);
7979 }
7980 #endif
7981 /*-----------------------------------------------------------------*/
7982 /* genGenPointerGet - gget value from generic pointer space        */
7983 /*-----------------------------------------------------------------*/
7984 static void genGenPointerGet (operand *left,
7985                               operand *result, iCode *ic)
7986 {
7987   int size, offset ;
7988   sym_link *retype = getSpec(operandType(result));
7989
7990   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7991   aopOp(left,ic,FALSE);
7992   aopOp(result,ic,FALSE);
7993
7994
7995   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7996
7997   /* if the operand is already in dptr 
7998      then we do nothing else we move the value to dptr */
7999   //  if (AOP_TYPE(left) != AOP_STR) {
8000     /* if this is remateriazable */
8001     if (AOP_TYPE(left) == AOP_IMMD) {
8002       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8003       pic14_emitcode("mov","b,#%d",pointerCode(retype));
8004     }
8005     else { /* we need to get it byte by byte */
8006
8007       emitpcode(POC_MOVFW,popGet(AOP(left),0));
8008       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8009
8010       size = AOP_SIZE(result);
8011       offset = 0 ;
8012
8013       while(size--) {
8014         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8015         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8016         if(size)
8017           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8018       }
8019       goto release;
8020     }
8021     //}
8022   /* so dptr know contains the address */
8023
8024   /* if bit then unpack */
8025   //if (IS_BITVAR(retype)) 
8026   //  genUnpackBits(result,"dptr",GPOINTER);
8027
8028  release:
8029   freeAsmop(left,NULL,ic,TRUE);
8030   freeAsmop(result,NULL,ic,TRUE);
8031
8032 }
8033
8034 /*-----------------------------------------------------------------*/
8035 /* genConstPointerGet - get value from const generic pointer space */
8036 /*-----------------------------------------------------------------*/
8037 static void genConstPointerGet (operand *left,
8038                                 operand *result, iCode *ic)
8039 {
8040   //sym_link *retype = getSpec(operandType(result));
8041   symbol *albl = newiTempLabel(NULL);
8042   symbol *blbl = newiTempLabel(NULL);
8043   PIC_OPCODE poc;
8044
8045   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8046   aopOp(left,ic,FALSE);
8047   aopOp(result,ic,FALSE);
8048
8049
8050   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8051
8052   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8053
8054   emitpcode(POC_CALL,popGetLabel(albl->key));
8055   emitpcode(POC_GOTO,popGetLabel(blbl->key));
8056   emitpLabel(albl->key);
8057
8058   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8059     
8060   emitpcode(poc,popGet(AOP(left),1));
8061   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8062   emitpcode(poc,popGet(AOP(left),0));
8063   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8064
8065   emitpLabel(blbl->key);
8066
8067   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8068
8069
8070   freeAsmop(left,NULL,ic,TRUE);
8071   freeAsmop(result,NULL,ic,TRUE);
8072
8073 }
8074 /*-----------------------------------------------------------------*/
8075 /* genPointerGet - generate code for pointer get                   */
8076 /*-----------------------------------------------------------------*/
8077 static void genPointerGet (iCode *ic)
8078 {
8079     operand *left, *result ;
8080     sym_link *type, *etype;
8081     int p_type;
8082
8083     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8084
8085     left = IC_LEFT(ic);
8086     result = IC_RESULT(ic) ;
8087
8088     /* depending on the type of pointer we need to
8089     move it to the correct pointer register */
8090     type = operandType(left);
8091     etype = getSpec(type);
8092
8093     if (IS_PTR_CONST(type))
8094       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8095
8096     /* if left is of type of pointer then it is simple */
8097     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8098         p_type = DCL_TYPE(type);
8099     else {
8100         /* we have to go by the storage class */
8101         p_type = PTR_TYPE(SPEC_OCLS(etype));
8102
8103         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8104
8105         if (SPEC_OCLS(etype)->codesp ) {
8106           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8107           //p_type = CPOINTER ; 
8108         }
8109         else
8110             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8111               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8112                /*p_type = FPOINTER ;*/ 
8113             else
8114                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8115                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8116 /*                  p_type = PPOINTER; */
8117                 else
8118                     if (SPEC_OCLS(etype) == idata )
8119                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8120 /*                      p_type = IPOINTER; */
8121                     else
8122                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8123 /*                      p_type = POINTER ; */
8124     }
8125
8126     /* now that we have the pointer type we assign
8127     the pointer values */
8128     switch (p_type) {
8129
8130     case POINTER:       
8131     case IPOINTER:
8132         genNearPointerGet (left,result,ic);
8133         break;
8134
8135     case PPOINTER:
8136         genPagedPointerGet(left,result,ic);
8137         break;
8138
8139     case FPOINTER:
8140         genFarPointerGet (left,result,ic);
8141         break;
8142
8143     case CPOINTER:
8144         genConstPointerGet (left,result,ic);
8145         //pic14_emitcodePointerGet (left,result,ic);
8146         break;
8147
8148     case GPOINTER:
8149       if (IS_PTR_CONST(type))
8150         genConstPointerGet (left,result,ic);
8151       else
8152         genGenPointerGet (left,result,ic);
8153       break;
8154     }
8155
8156 }
8157
8158 /*-----------------------------------------------------------------*/
8159 /* genPackBits - generates code for packed bit storage             */
8160 /*-----------------------------------------------------------------*/
8161 static void genPackBits (sym_link    *etype ,
8162                          operand *right ,
8163                          char *rname, int p_type)
8164 {
8165     int shCount = 0 ;
8166     int offset = 0  ;
8167     int rLen = 0 ;
8168     int blen, bstr ;   
8169     char *l ;
8170
8171     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8172     blen = SPEC_BLEN(etype);
8173     bstr = SPEC_BSTR(etype);
8174
8175     l = aopGet(AOP(right),offset++,FALSE,FALSE);
8176     MOVA(l);   
8177
8178     /* if the bit lenth is less than or    */
8179     /* it exactly fits a byte then         */
8180     if (SPEC_BLEN(etype) <= 8 )  {
8181         shCount = SPEC_BSTR(etype) ;
8182
8183         /* shift left acc */
8184         AccLsh(shCount);
8185
8186         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8187
8188
8189             switch (p_type) {
8190                 case POINTER:
8191                     pic14_emitcode ("mov","b,a");
8192                     pic14_emitcode("mov","a,@%s",rname);
8193                     break;
8194
8195                 case FPOINTER:
8196                     pic14_emitcode ("mov","b,a");
8197                     pic14_emitcode("movx","a,@dptr");
8198                     break;
8199
8200                 case GPOINTER:
8201                     pic14_emitcode ("push","b");
8202                     pic14_emitcode ("push","acc");
8203                     pic14_emitcode ("lcall","__gptrget");
8204                     pic14_emitcode ("pop","b");
8205                     break;
8206             }
8207
8208             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8209                       ((unsigned char)(0xFF << (blen+bstr)) | 
8210                        (unsigned char)(0xFF >> (8-bstr)) ) );
8211             pic14_emitcode ("orl","a,b");
8212             if (p_type == GPOINTER)
8213                 pic14_emitcode("pop","b");
8214         }
8215     }
8216
8217     switch (p_type) {
8218         case POINTER:
8219             pic14_emitcode("mov","@%s,a",rname);
8220             break;
8221
8222         case FPOINTER:
8223             pic14_emitcode("movx","@dptr,a");
8224             break;
8225
8226         case GPOINTER:
8227             DEBUGpic14_emitcode(";lcall","__gptrput");
8228             break;
8229     }
8230
8231     /* if we r done */
8232     if ( SPEC_BLEN(etype) <= 8 )
8233         return ;
8234
8235     pic14_emitcode("inc","%s",rname);
8236     rLen = SPEC_BLEN(etype) ;     
8237
8238     /* now generate for lengths greater than one byte */
8239     while (1) {
8240
8241         l = aopGet(AOP(right),offset++,FALSE,TRUE);
8242
8243         rLen -= 8 ;
8244         if (rLen <= 0 )
8245             break ;
8246
8247         switch (p_type) {
8248             case POINTER:
8249                 if (*l == '@') {
8250                     MOVA(l);
8251                     pic14_emitcode("mov","@%s,a",rname);
8252                 } else
8253                     pic14_emitcode("mov","@%s,%s",rname,l);
8254                 break;
8255
8256             case FPOINTER:
8257                 MOVA(l);
8258                 pic14_emitcode("movx","@dptr,a");
8259                 break;
8260
8261             case GPOINTER:
8262                 MOVA(l);
8263                 DEBUGpic14_emitcode(";lcall","__gptrput");
8264                 break;  
8265         }   
8266         pic14_emitcode ("inc","%s",rname);
8267     }
8268
8269     MOVA(l);
8270
8271     /* last last was not complete */
8272     if (rLen)   {
8273         /* save the byte & read byte */
8274         switch (p_type) {
8275             case POINTER:
8276                 pic14_emitcode ("mov","b,a");
8277                 pic14_emitcode("mov","a,@%s",rname);
8278                 break;
8279
8280             case FPOINTER:
8281                 pic14_emitcode ("mov","b,a");
8282                 pic14_emitcode("movx","a,@dptr");
8283                 break;
8284
8285             case GPOINTER:
8286                 pic14_emitcode ("push","b");
8287                 pic14_emitcode ("push","acc");
8288                 pic14_emitcode ("lcall","__gptrget");
8289                 pic14_emitcode ("pop","b");
8290                 break;
8291         }
8292
8293         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8294         pic14_emitcode ("orl","a,b");
8295     }
8296
8297     if (p_type == GPOINTER)
8298         pic14_emitcode("pop","b");
8299
8300     switch (p_type) {
8301
8302     case POINTER:
8303         pic14_emitcode("mov","@%s,a",rname);
8304         break;
8305         
8306     case FPOINTER:
8307         pic14_emitcode("movx","@dptr,a");
8308         break;
8309         
8310     case GPOINTER:
8311         DEBUGpic14_emitcode(";lcall","__gptrput");
8312         break;                  
8313     }
8314 }
8315 /*-----------------------------------------------------------------*/
8316 /* genDataPointerSet - remat pointer to data space                 */
8317 /*-----------------------------------------------------------------*/
8318 static void genDataPointerSet(operand *right,
8319                               operand *result,
8320                               iCode *ic)
8321 {
8322     int size, offset = 0 ;
8323     char *l, buffer[256];
8324
8325     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8326     aopOp(right,ic,FALSE);
8327     
8328     l = aopGet(AOP(result),0,FALSE,TRUE);
8329     size = AOP_SIZE(right);
8330 /*
8331     if ( AOP_TYPE(result) == AOP_PCODE) {
8332       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8333               AOP(result)->aopu.pcop->name,
8334               PCOI(AOP(result)->aopu.pcop)->offset);
8335     }
8336 */
8337
8338     // tsd, was l+1 - the underline `_' prefix was being stripped
8339     while (size--) {
8340       if (offset) {
8341         sprintf(buffer,"(%s + %d)",l,offset);
8342         fprintf(stderr,"oops  %s\n",buffer);
8343       } else
8344         sprintf(buffer,"%s",l);
8345
8346         if (AOP_TYPE(right) == AOP_LIT) {
8347           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8348           lit = lit >> (8*offset);
8349           if(lit&0xff) {
8350             pic14_emitcode("movlw","%d",lit);
8351             pic14_emitcode("movwf","%s",buffer);
8352
8353             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8354             //emitpcode(POC_MOVWF, popRegFromString(buffer));
8355             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8356
8357           } else {
8358             pic14_emitcode("clrf","%s",buffer);
8359             //emitpcode(POC_CLRF, popRegFromString(buffer));
8360             emitpcode(POC_CLRF, popGet(AOP(result),0));
8361           }
8362         }else {
8363           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8364           pic14_emitcode("movwf","%s",buffer);
8365
8366           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8367           //emitpcode(POC_MOVWF, popRegFromString(buffer));
8368           emitpcode(POC_MOVWF, popGet(AOP(result),0));
8369
8370         }
8371
8372         offset++;
8373     }
8374
8375     freeAsmop(right,NULL,ic,TRUE);
8376     freeAsmop(result,NULL,ic,TRUE);
8377 }
8378
8379 /*-----------------------------------------------------------------*/
8380 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8381 /*-----------------------------------------------------------------*/
8382 static void genNearPointerSet (operand *right,
8383                                operand *result, 
8384                                iCode *ic)
8385 {
8386     asmop *aop = NULL;
8387     char *l;
8388     sym_link *retype;
8389     sym_link *ptype = operandType(result);
8390
8391     
8392     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8393     retype= getSpec(operandType(right));
8394
8395     aopOp(result,ic,FALSE);
8396     
8397     /* if the result is rematerializable &
8398        in data space & not a bit variable */
8399     //if (AOP_TYPE(result) == AOP_IMMD &&
8400     if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8401         DCL_TYPE(ptype) == POINTER   &&
8402         !IS_BITVAR(retype)) {
8403         genDataPointerSet (right,result,ic);
8404         return;
8405     }
8406
8407     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8408
8409     /* if the value is already in a pointer register
8410     then don't need anything more */
8411     if (!AOP_INPREG(AOP(result))) {
8412         /* otherwise get a free pointer register */
8413         //aop = newAsmop(0);
8414         //preg = getFreePtr(ic,&aop,FALSE);
8415         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8416         //pic14_emitcode("mov","%s,%s",
8417         //         preg->name,
8418         //         aopGet(AOP(result),0,FALSE,TRUE));
8419         //rname = preg->name ;
8420         pic14_emitcode("movwf","fsr");
8421     }// else
8422     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8423
8424     freeAsmop(result,NULL,ic,TRUE);
8425     aopOp (right,ic,FALSE);
8426     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8427
8428     /* if bitfield then unpack the bits */
8429     if (IS_BITVAR(retype)) {
8430       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8431              "The programmer is obviously confused");
8432       //genPackBits (retype,right,rname,POINTER);
8433       exit(1);
8434     }
8435     else {
8436         /* we have can just get the values */
8437         int size = AOP_SIZE(right);
8438         int offset = 0 ;    
8439
8440     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8441         while (size--) {
8442             l = aopGet(AOP(right),offset,FALSE,TRUE);
8443             if (*l == '@' ) {
8444               //MOVA(l);
8445               //pic14_emitcode("mov","@%s,a",rname);
8446               pic14_emitcode("movf","indf,w ;1");
8447             } else {
8448
8449               if (AOP_TYPE(right) == AOP_LIT) {
8450                 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8451                 if(lit) {
8452                   pic14_emitcode("movlw","%s",l);
8453                   pic14_emitcode("movwf","indf ;2");
8454                 } else 
8455                   pic14_emitcode("clrf","indf");
8456               }else {
8457                 pic14_emitcode("movf","%s,w",l);
8458                 pic14_emitcode("movwf","indf ;2");
8459               }
8460             //pic14_emitcode("mov","@%s,%s",rname,l);
8461             }
8462             if (size)
8463               pic14_emitcode("incf","fsr,f ;3");
8464             //pic14_emitcode("inc","%s",rname);
8465             offset++;
8466         }
8467     }
8468
8469     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8470     /* now some housekeeping stuff */
8471     if (aop) {
8472         /* we had to allocate for this iCode */
8473         freeAsmop(NULL,aop,ic,TRUE);
8474     } else { 
8475         /* we did not allocate which means left
8476         already in a pointer register, then
8477         if size > 0 && this could be used again
8478         we have to point it back to where it 
8479         belongs */
8480     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8481         if (AOP_SIZE(right) > 1 &&
8482             !OP_SYMBOL(result)->remat &&
8483             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8484               ic->depth )) {
8485             int size = AOP_SIZE(right) - 1;
8486             while (size--)
8487               pic14_emitcode("decf","fsr,f");
8488               //pic14_emitcode("dec","%s",rname);
8489         }
8490     }
8491
8492     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8493     /* done */
8494     freeAsmop(right,NULL,ic,TRUE);
8495
8496
8497 }
8498
8499 /*-----------------------------------------------------------------*/
8500 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8501 /*-----------------------------------------------------------------*/
8502 static void genPagedPointerSet (operand *right,
8503                                operand *result, 
8504                                iCode *ic)
8505 {
8506     asmop *aop = NULL;
8507     regs *preg = NULL ;
8508     char *rname , *l;
8509     sym_link *retype;
8510        
8511     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8512
8513     retype= getSpec(operandType(right));
8514     
8515     aopOp(result,ic,FALSE);
8516     
8517     /* if the value is already in a pointer register
8518        then don't need anything more */
8519     if (!AOP_INPREG(AOP(result))) {
8520         /* otherwise get a free pointer register */
8521         aop = newAsmop(0);
8522         preg = getFreePtr(ic,&aop,FALSE);
8523         pic14_emitcode("mov","%s,%s",
8524                 preg->name,
8525                 aopGet(AOP(result),0,FALSE,TRUE));
8526         rname = preg->name ;
8527     } else
8528         rname = aopGet(AOP(result),0,FALSE,FALSE);
8529     
8530     freeAsmop(result,NULL,ic,TRUE);
8531     aopOp (right,ic,FALSE);
8532
8533     /* if bitfield then unpack the bits */
8534     if (IS_BITVAR(retype)) 
8535         genPackBits (retype,right,rname,PPOINTER);
8536     else {
8537         /* we have can just get the values */
8538         int size = AOP_SIZE(right);
8539         int offset = 0 ;        
8540         
8541         while (size--) {
8542             l = aopGet(AOP(right),offset,FALSE,TRUE);
8543             
8544             MOVA(l);
8545             pic14_emitcode("movx","@%s,a",rname);
8546
8547             if (size)
8548                 pic14_emitcode("inc","%s",rname);
8549
8550             offset++;
8551         }
8552     }
8553     
8554     /* now some housekeeping stuff */
8555     if (aop) {
8556         /* we had to allocate for this iCode */
8557         freeAsmop(NULL,aop,ic,TRUE);
8558     } else { 
8559         /* we did not allocate which means left
8560            already in a pointer register, then
8561            if size > 0 && this could be used again
8562            we have to point it back to where it 
8563            belongs */
8564         if (AOP_SIZE(right) > 1 &&
8565             !OP_SYMBOL(result)->remat &&
8566             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8567               ic->depth )) {
8568             int size = AOP_SIZE(right) - 1;
8569             while (size--)
8570                 pic14_emitcode("dec","%s",rname);
8571         }
8572     }
8573
8574     /* done */
8575     freeAsmop(right,NULL,ic,TRUE);
8576     
8577         
8578 }
8579
8580 /*-----------------------------------------------------------------*/
8581 /* genFarPointerSet - set value from far space                     */
8582 /*-----------------------------------------------------------------*/
8583 static void genFarPointerSet (operand *right,
8584                               operand *result, iCode *ic)
8585 {
8586     int size, offset ;
8587     sym_link *retype = getSpec(operandType(right));
8588
8589     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8590     aopOp(result,ic,FALSE);
8591
8592     /* if the operand is already in dptr 
8593     then we do nothing else we move the value to dptr */
8594     if (AOP_TYPE(result) != AOP_STR) {
8595         /* if this is remateriazable */
8596         if (AOP_TYPE(result) == AOP_IMMD)
8597             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8598         else { /* we need to get it byte by byte */
8599             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8600             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8601             if (options.model == MODEL_FLAT24)
8602             {
8603                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8604             }
8605         }
8606     }
8607     /* so dptr know contains the address */
8608     freeAsmop(result,NULL,ic,TRUE);
8609     aopOp(right,ic,FALSE);
8610
8611     /* if bit then unpack */
8612     if (IS_BITVAR(retype)) 
8613         genPackBits(retype,right,"dptr",FPOINTER);
8614     else {
8615         size = AOP_SIZE(right);
8616         offset = 0 ;
8617
8618         while (size--) {
8619             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8620             MOVA(l);
8621             pic14_emitcode("movx","@dptr,a");
8622             if (size)
8623                 pic14_emitcode("inc","dptr");
8624         }
8625     }
8626
8627     freeAsmop(right,NULL,ic,TRUE);
8628 }
8629
8630 /*-----------------------------------------------------------------*/
8631 /* genGenPointerSet - set value from generic pointer space         */
8632 /*-----------------------------------------------------------------*/
8633 static void genGenPointerSet (operand *right,
8634                               operand *result, iCode *ic)
8635 {
8636   int size, offset ;
8637   sym_link *retype = getSpec(operandType(right));
8638
8639   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8640
8641   aopOp(result,ic,FALSE);
8642   aopOp(right,ic,FALSE);
8643   size = AOP_SIZE(right);
8644
8645   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8646
8647   /* if the operand is already in dptr 
8648      then we do nothing else we move the value to dptr */
8649   if (AOP_TYPE(result) != AOP_STR) {
8650     /* if this is remateriazable */
8651     if (AOP_TYPE(result) == AOP_IMMD) {
8652       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8653       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8654     }
8655     else { /* we need to get it byte by byte */
8656       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8657       size = AOP_SIZE(right);
8658       offset = 0 ;
8659
8660       /* hack hack! see if this the FSR. If so don't load W */
8661       if(AOP_TYPE(right) != AOP_ACC) {
8662
8663         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8664         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8665
8666         //if(size==2)
8667         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8668         //if(size==4) {
8669         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8670         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8671         //}
8672
8673         while(size--) {
8674           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8675           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8676           
8677           if(size)
8678             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8679         }
8680
8681
8682         goto release;
8683       } 
8684
8685       if(aopIdx(AOP(result),0) != 4) {
8686
8687         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8688         goto release;
8689       }
8690
8691       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8692       goto release;
8693
8694     }
8695   }
8696   /* so dptr know contains the address */
8697
8698
8699   /* if bit then unpack */
8700   if (IS_BITVAR(retype)) 
8701     genPackBits(retype,right,"dptr",GPOINTER);
8702   else {
8703     size = AOP_SIZE(right);
8704     offset = 0 ;
8705
8706     while (--size) {
8707       //char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8708       if(size)
8709         pic14_emitcode("incf","fsr,f");
8710       pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8711       pic14_emitcode("movwf","indf");
8712       //MOVA(l);
8713       //DEBUGpic14_emitcode(";lcall","__gptrput");
8714       //if (size)
8715       //    pic14_emitcode("inc","dptr");
8716     }
8717   }
8718
8719  release:
8720   freeAsmop(right,NULL,ic,TRUE);
8721   freeAsmop(result,NULL,ic,TRUE);
8722 }
8723
8724 /*-----------------------------------------------------------------*/
8725 /* genPointerSet - stores the value into a pointer location        */
8726 /*-----------------------------------------------------------------*/
8727 static void genPointerSet (iCode *ic)
8728 {    
8729     operand *right, *result ;
8730     sym_link *type, *etype;
8731     int p_type;
8732
8733     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8734
8735     right = IC_RIGHT(ic);
8736     result = IC_RESULT(ic) ;
8737
8738     /* depending on the type of pointer we need to
8739     move it to the correct pointer register */
8740     type = operandType(result);
8741     etype = getSpec(type);
8742     /* if left is of type of pointer then it is simple */
8743     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8744         p_type = DCL_TYPE(type);
8745     }
8746     else {
8747         /* we have to go by the storage class */
8748         p_type = PTR_TYPE(SPEC_OCLS(etype));
8749
8750 /*      if (SPEC_OCLS(etype)->codesp ) { */
8751 /*          p_type = CPOINTER ;  */
8752 /*      } */
8753 /*      else */
8754 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8755 /*              p_type = FPOINTER ; */
8756 /*          else */
8757 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8758 /*                  p_type = PPOINTER ; */
8759 /*              else */
8760 /*                  if (SPEC_OCLS(etype) == idata ) */
8761 /*                      p_type = IPOINTER ; */
8762 /*                  else */
8763 /*                      p_type = POINTER ; */
8764     }
8765
8766     /* now that we have the pointer type we assign
8767     the pointer values */
8768     switch (p_type) {
8769
8770     case POINTER:
8771     case IPOINTER:
8772         genNearPointerSet (right,result,ic);
8773         break;
8774
8775     case PPOINTER:
8776         genPagedPointerSet (right,result,ic);
8777         break;
8778
8779     case FPOINTER:
8780         genFarPointerSet (right,result,ic);
8781         break;
8782
8783     case GPOINTER:
8784         genGenPointerSet (right,result,ic);
8785         break;
8786
8787     default:
8788       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
8789               "genPointerSet: illegal pointer type");
8790     }
8791 }
8792
8793 /*-----------------------------------------------------------------*/
8794 /* genIfx - generate code for Ifx statement                        */
8795 /*-----------------------------------------------------------------*/
8796 static void genIfx (iCode *ic, iCode *popIc)
8797 {
8798   operand *cond = IC_COND(ic);
8799   int isbit =0;
8800
8801   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8802
8803   aopOp(cond,ic,FALSE);
8804
8805   /* get the value into acc */
8806   if (AOP_TYPE(cond) != AOP_CRY)
8807     pic14_toBoolean(cond);
8808   else
8809     isbit = 1;
8810   /* the result is now in the accumulator */
8811   freeAsmop(cond,NULL,ic,TRUE);
8812
8813   /* if there was something to be popped then do it */
8814   if (popIc)
8815     genIpop(popIc);
8816
8817   /* if the condition is  a bit variable */
8818   if (isbit && IS_ITEMP(cond) && 
8819       SPIL_LOC(cond)) {
8820     genIfxJump(ic,SPIL_LOC(cond)->rname);
8821     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8822   }
8823   else {
8824     if (isbit && !IS_ITEMP(cond))
8825       genIfxJump(ic,OP_SYMBOL(cond)->rname);
8826     else
8827       genIfxJump(ic,"a");
8828   }
8829   ic->generated = 1;
8830
8831 }
8832
8833 /*-----------------------------------------------------------------*/
8834 /* genAddrOf - generates code for address of                       */
8835 /*-----------------------------------------------------------------*/
8836 static void genAddrOf (iCode *ic)
8837 {
8838   operand *right, *result, *left;
8839   int size, offset ;
8840
8841   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8842
8843
8844   //aopOp(IC_RESULT(ic),ic,FALSE);
8845
8846   aopOp((left=IC_LEFT(ic)),ic,FALSE);
8847   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8848   aopOp((result=IC_RESULT(ic)),ic,TRUE);
8849
8850   DEBUGpic14_AopType(__LINE__,left,right,result);
8851
8852   size = AOP_SIZE(IC_RESULT(ic));
8853   offset = 0;
8854
8855   while (size--) {
8856     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
8857     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8858     offset++;
8859   }
8860
8861   freeAsmop(left,NULL,ic,FALSE);
8862   freeAsmop(result,NULL,ic,TRUE);
8863
8864 }
8865
8866 #if 0
8867 /*-----------------------------------------------------------------*/
8868 /* genFarFarAssign - assignment when both are in far space         */
8869 /*-----------------------------------------------------------------*/
8870 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8871 {
8872     int size = AOP_SIZE(right);
8873     int offset = 0;
8874     char *l ;
8875     /* first push the right side on to the stack */
8876     while (size--) {
8877         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8878         MOVA(l);
8879         pic14_emitcode ("push","acc");
8880     }
8881     
8882     freeAsmop(right,NULL,ic,FALSE);
8883     /* now assign DPTR to result */
8884     aopOp(result,ic,FALSE);
8885     size = AOP_SIZE(result);
8886     while (size--) {
8887         pic14_emitcode ("pop","acc");
8888         aopPut(AOP(result),"a",--offset);
8889     }
8890     freeAsmop(result,NULL,ic,FALSE);
8891         
8892 }
8893 #endif
8894
8895 /*-----------------------------------------------------------------*/
8896 /* genAssign - generate code for assignment                        */
8897 /*-----------------------------------------------------------------*/
8898 static void genAssign (iCode *ic)
8899 {
8900   operand *result, *right;
8901   int size, offset,know_W;
8902   unsigned long lit = 0L;
8903
8904   result = IC_RESULT(ic);
8905   right  = IC_RIGHT(ic) ;
8906
8907   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8908
8909   /* if they are the same */
8910   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8911     return ;
8912
8913   aopOp(right,ic,FALSE);
8914   aopOp(result,ic,TRUE);
8915
8916   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8917
8918   /* if they are the same registers */
8919   if (pic14_sameRegs(AOP(right),AOP(result)))
8920     goto release;
8921
8922   /* if the result is a bit */
8923   if (AOP_TYPE(result) == AOP_CRY) {
8924
8925     /* if the right size is a literal then
8926        we know what the value is */
8927     if (AOP_TYPE(right) == AOP_LIT) {
8928           
8929       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8930                   popGet(AOP(result),0));
8931
8932       if (((int) operandLitValue(right))) 
8933         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8934                        AOP(result)->aopu.aop_dir,
8935                        AOP(result)->aopu.aop_dir);
8936       else
8937         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8938                        AOP(result)->aopu.aop_dir,
8939                        AOP(result)->aopu.aop_dir);
8940       goto release;
8941     }
8942
8943     /* the right is also a bit variable */
8944     if (AOP_TYPE(right) == AOP_CRY) {
8945       emitpcode(POC_BCF,    popGet(AOP(result),0));
8946       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8947       emitpcode(POC_BSF,    popGet(AOP(result),0));
8948
8949       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8950                      AOP(result)->aopu.aop_dir,
8951                      AOP(result)->aopu.aop_dir);
8952       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8953                      AOP(right)->aopu.aop_dir,
8954                      AOP(right)->aopu.aop_dir);
8955       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8956                      AOP(result)->aopu.aop_dir,
8957                      AOP(result)->aopu.aop_dir);
8958       goto release ;
8959     }
8960
8961     /* we need to or */
8962     emitpcode(POC_BCF,    popGet(AOP(result),0));
8963     pic14_toBoolean(right);
8964     emitSKPZ;
8965     emitpcode(POC_BSF,    popGet(AOP(result),0));
8966     //aopPut(AOP(result),"a",0);
8967     goto release ;
8968   }
8969
8970   /* bit variables done */
8971   /* general case */
8972   size = AOP_SIZE(result);
8973   offset = 0 ;
8974   if(AOP_TYPE(right) == AOP_LIT)
8975     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8976
8977   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
8978   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8979     if(aopIdx(AOP(result),0) == 4) {
8980   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8981       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8982       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8983       goto release;
8984     } else
8985       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
8986   }
8987
8988   know_W=-1;
8989   while (size--) {
8990   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8991     if(AOP_TYPE(right) == AOP_LIT) {
8992       if(lit&0xff) {
8993         if(know_W != (lit&0xff))
8994           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8995         know_W = lit&0xff;
8996         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8997       } else
8998         emitpcode(POC_CLRF, popGet(AOP(result),offset));
8999
9000       lit >>= 8;
9001
9002     } else if (AOP_TYPE(right) == AOP_CRY) {
9003       emitpcode(POC_CLRF, popGet(AOP(result),offset));
9004       if(offset == 0) {
9005         emitpcode(POC_BTFSS, popGet(AOP(right),0));
9006         emitpcode(POC_INCF, popGet(AOP(result),0));
9007       }
9008     } else {
9009   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9010       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9011       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9012     }
9013             
9014     offset++;
9015   }
9016
9017     
9018  release:
9019   freeAsmop (right,NULL,ic,FALSE);
9020   freeAsmop (result,NULL,ic,TRUE);
9021 }   
9022
9023 /*-----------------------------------------------------------------*/
9024 /* genJumpTab - genrates code for jump table                       */
9025 /*-----------------------------------------------------------------*/
9026 static void genJumpTab (iCode *ic)
9027 {
9028     symbol *jtab;
9029     char *l;
9030
9031     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9032
9033     aopOp(IC_JTCOND(ic),ic,FALSE);
9034     /* get the condition into accumulator */
9035     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9036     MOVA(l);
9037     /* multiply by three */
9038     pic14_emitcode("add","a,acc");
9039     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9040
9041     jtab = newiTempLabel(NULL);
9042     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9043     pic14_emitcode("jmp","@a+dptr");
9044     pic14_emitcode("","%05d_DS_:",jtab->key+100);
9045
9046     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9047     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9048     emitSKPNC;
9049     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9050     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9051     emitpLabel(jtab->key);
9052
9053     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9054
9055     /* now generate the jump labels */
9056     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9057          jtab = setNextItem(IC_JTLABELS(ic))) {
9058         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9059         emitpcode(POC_GOTO,popGetLabel(jtab->key));
9060         
9061     }
9062
9063 }
9064
9065 /*-----------------------------------------------------------------*/
9066 /* genMixedOperation - gen code for operators between mixed types  */
9067 /*-----------------------------------------------------------------*/
9068 /*
9069   TSD - Written for the PIC port - but this unfortunately is buggy.
9070   This routine is good in that it is able to efficiently promote 
9071   types to different (larger) sizes. Unfortunately, the temporary
9072   variables that are optimized out by this routine are sometimes
9073   used in other places. So until I know how to really parse the 
9074   iCode tree, I'm going to not be using this routine :(.
9075 */
9076 static int genMixedOperation (iCode *ic)
9077 {
9078 #if 0
9079   operand *result = IC_RESULT(ic);
9080   sym_link *ctype = operandType(IC_LEFT(ic));
9081   operand *right = IC_RIGHT(ic);
9082   int ret = 0;
9083   int big,small;
9084   int offset;
9085
9086   iCode *nextic;
9087   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9088
9089   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9090
9091   nextic = ic->next;
9092   if(!nextic)
9093     return 0;
9094
9095   nextright = IC_RIGHT(nextic);
9096   nextleft  = IC_LEFT(nextic);
9097   nextresult = IC_RESULT(nextic);
9098
9099   aopOp(right,ic,FALSE);
9100   aopOp(result,ic,FALSE);
9101   aopOp(nextright,  nextic, FALSE);
9102   aopOp(nextleft,   nextic, FALSE);
9103   aopOp(nextresult, nextic, FALSE);
9104
9105   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9106
9107     operand *t = right;
9108     right = nextright;
9109     nextright = t; 
9110
9111     pic14_emitcode(";remove right +","");
9112
9113   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9114 /*
9115     operand *t = right;
9116     right = nextleft;
9117     nextleft = t; 
9118 */
9119     pic14_emitcode(";remove left +","");
9120   } else
9121     return 0;
9122
9123   big = AOP_SIZE(nextleft);
9124   small = AOP_SIZE(nextright);
9125
9126   switch(nextic->op) {
9127
9128   case '+':
9129     pic14_emitcode(";optimize a +","");
9130     /* if unsigned or not an integral type */
9131     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9132       pic14_emitcode(";add a bit to something","");
9133     } else {
9134
9135       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9136
9137       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9138         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9139         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9140       } else
9141         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9142
9143       offset = 0;
9144       while(--big) {
9145
9146         offset++;
9147
9148         if(--small) {
9149           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9150             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9151             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9152           }
9153
9154           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9155           emitSKPNC;
9156           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9157                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9158                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9159           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9160           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9161
9162         } else {
9163           pic14_emitcode("rlf","known_zero,w");
9164
9165           /*
9166             if right is signed
9167               btfsc  right,7
9168                addlw ff
9169           */
9170           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9171             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9172             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9173           } else {
9174             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9175           }
9176         }
9177       }
9178       ret = 1;
9179     }
9180   }
9181   ret = 1;
9182
9183 release:
9184   freeAsmop(right,NULL,ic,TRUE);
9185   freeAsmop(result,NULL,ic,TRUE);
9186   freeAsmop(nextright,NULL,ic,TRUE);
9187   freeAsmop(nextleft,NULL,ic,TRUE);
9188   if(ret)
9189     nextic->generated = 1;
9190
9191   return ret;
9192 #else
9193   return 0;
9194 #endif
9195 }
9196 /*-----------------------------------------------------------------*/
9197 /* genCast - gen code for casting                                  */
9198 /*-----------------------------------------------------------------*/
9199 static void genCast (iCode *ic)
9200 {
9201     operand *result = IC_RESULT(ic);
9202     sym_link *ctype = operandType(IC_LEFT(ic));
9203     sym_link *rtype = operandType(IC_RIGHT(ic));
9204     operand *right = IC_RIGHT(ic);
9205     int size, offset ;
9206
9207     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9208     /* if they are equivalent then do nothing */
9209     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9210         return ;
9211
9212     aopOp(right,ic,FALSE) ;
9213     aopOp(result,ic,FALSE);
9214
9215     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9216
9217     /* if the result is a bit */
9218     if (AOP_TYPE(result) == AOP_CRY) {
9219         /* if the right size is a literal then
9220         we know what the value is */
9221       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9222         if (AOP_TYPE(right) == AOP_LIT) {
9223
9224           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9225                       popGet(AOP(result),0));
9226
9227             if (((int) operandLitValue(right))) 
9228               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9229                        AOP(result)->aopu.aop_dir,
9230                        AOP(result)->aopu.aop_dir);
9231             else
9232               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9233                        AOP(result)->aopu.aop_dir,
9234                        AOP(result)->aopu.aop_dir);
9235
9236             goto release;
9237         }
9238
9239         /* the right is also a bit variable */
9240         if (AOP_TYPE(right) == AOP_CRY) {
9241
9242           emitCLRC;
9243           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9244
9245           pic14_emitcode("clrc","");
9246           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9247                    AOP(right)->aopu.aop_dir,
9248                    AOP(right)->aopu.aop_dir);
9249             aopPut(AOP(result),"c",0);
9250             goto release ;
9251         }
9252
9253         /* we need to or */
9254         if (AOP_TYPE(right) == AOP_REG) {
9255           emitpcode(POC_BCF,    popGet(AOP(result),0));
9256           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9257           emitpcode(POC_BSF,    popGet(AOP(result),0));
9258         }
9259         pic14_toBoolean(right);
9260         aopPut(AOP(result),"a",0);
9261         goto release ;
9262     }
9263
9264     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9265       int offset = 1;
9266       size = AOP_SIZE(result);
9267
9268       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9269
9270       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9271       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9272       emitpcode(POC_INCF,   popGet(AOP(result),0));
9273
9274       while (size--)
9275         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9276
9277       goto release;
9278     }
9279
9280     /* if they are the same size : or less */
9281     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9282
9283         /* if they are in the same place */
9284       if (pic14_sameRegs(AOP(right),AOP(result)))
9285         goto release;
9286
9287       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9288       if (IS_PTR_CONST(rtype))
9289         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9290       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9291         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9292
9293       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9294         emitpcode(POC_MOVLW, popGet(AOP(right),0));
9295         emitpcode(POC_MOVWF, popGet(AOP(result),0));
9296         emitpcode(POC_MOVLW, popGet(AOP(right),1));
9297         emitpcode(POC_MOVWF, popGet(AOP(result),1));
9298         if(AOP_SIZE(result) <2)
9299           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9300
9301       } else {
9302
9303         /* if they in different places then copy */
9304         size = AOP_SIZE(result);
9305         offset = 0 ;
9306         while (size--) {
9307           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9308           emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9309
9310           //aopPut(AOP(result),
9311           // aopGet(AOP(right),offset,FALSE,FALSE),
9312           // offset);
9313
9314           offset++;
9315         }
9316       }
9317       goto release;
9318     }
9319
9320
9321     /* if the result is of type pointer */
9322     if (IS_PTR(ctype)) {
9323
9324         int p_type;
9325         sym_link *type = operandType(right);
9326         sym_link *etype = getSpec(type);
9327       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9328
9329         /* pointer to generic pointer */
9330         if (IS_GENPTR(ctype)) {
9331             char *l = zero;
9332             
9333             if (IS_PTR(type)) 
9334                 p_type = DCL_TYPE(type);
9335             else {
9336                 /* we have to go by the storage class */
9337                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9338
9339 /*              if (SPEC_OCLS(etype)->codesp )  */
9340 /*                  p_type = CPOINTER ;  */
9341 /*              else */
9342 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9343 /*                      p_type = FPOINTER ; */
9344 /*                  else */
9345 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9346 /*                          p_type = PPOINTER; */
9347 /*                      else */
9348 /*                          if (SPEC_OCLS(etype) == idata ) */
9349 /*                              p_type = IPOINTER ; */
9350 /*                          else */
9351 /*                              p_type = POINTER ; */
9352             }
9353                 
9354             /* the first two bytes are known */
9355             size = GPTRSIZE - 1; 
9356             offset = 0 ;
9357             while (size--) {
9358               if(offset < AOP_SIZE(right))
9359                 aopPut(AOP(result),
9360                        aopGet(AOP(right),offset,FALSE,FALSE),
9361                        offset);
9362               else
9363                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9364               offset++;
9365             }
9366             /* the last byte depending on type */
9367             switch (p_type) {
9368             case IPOINTER:
9369             case POINTER:
9370                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9371                 break;
9372             case FPOINTER:
9373               pic14_emitcode(";BUG!? ","%d",__LINE__);
9374                 l = one;
9375                 break;
9376             case CPOINTER:
9377               pic14_emitcode(";BUG!? ","%d",__LINE__);
9378                 l = "#0x02";
9379                 break;                          
9380             case PPOINTER:
9381               pic14_emitcode(";BUG!? ","%d",__LINE__);
9382                 l = "#0x03";
9383                 break;
9384                 
9385             default:
9386                 /* this should never happen */
9387                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9388                        "got unknown pointer type");
9389                 exit(1);
9390             }
9391             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9392             goto release ;
9393         }
9394         
9395         /* just copy the pointers */
9396         size = AOP_SIZE(result);
9397         offset = 0 ;
9398         while (size--) {
9399             aopPut(AOP(result),
9400                    aopGet(AOP(right),offset,FALSE,FALSE),
9401                    offset);
9402             offset++;
9403         }
9404         goto release ;
9405     }
9406     
9407
9408
9409     /* so we now know that the size of destination is greater
9410     than the size of the source.
9411     Now, if the next iCode is an operator then we might be
9412     able to optimize the operation without performing a cast.
9413     */
9414     if(genMixedOperation(ic))
9415       goto release;
9416
9417     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9418     
9419     /* we move to result for the size of source */
9420     size = AOP_SIZE(right);
9421     offset = 0 ;
9422     while (size--) {
9423       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9424       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9425       offset++;
9426     }
9427
9428     /* now depending on the sign of the destination */
9429     size = AOP_SIZE(result) - AOP_SIZE(right);
9430     /* if unsigned or not an integral type */
9431     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9432       while (size--)
9433         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9434     } else {
9435       /* we need to extend the sign :{ */
9436
9437       if(size == 1) {
9438         /* Save one instruction of casting char to int */
9439         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9440         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9441         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9442       } else {
9443         emitpcodeNULLop(POC_CLRW);
9444
9445         if(offset)
9446           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9447         else
9448           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9449         
9450         emitpcode(POC_MOVLW,   popGetLit(0xff));
9451
9452         while (size--)
9453           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9454       }
9455     }
9456
9457 release:
9458     freeAsmop(right,NULL,ic,TRUE);
9459     freeAsmop(result,NULL,ic,TRUE);
9460
9461 }
9462
9463 /*-----------------------------------------------------------------*/
9464 /* genDjnz - generate decrement & jump if not zero instrucion      */
9465 /*-----------------------------------------------------------------*/
9466 static int genDjnz (iCode *ic, iCode *ifx)
9467 {
9468     symbol *lbl, *lbl1;
9469     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9470
9471     if (!ifx)
9472         return 0;
9473     
9474     /* if the if condition has a false label
9475        then we cannot save */
9476     if (IC_FALSE(ifx))
9477         return 0;
9478
9479     /* if the minus is not of the form 
9480        a = a - 1 */
9481     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9482         !IS_OP_LITERAL(IC_RIGHT(ic)))
9483         return 0;
9484
9485     if (operandLitValue(IC_RIGHT(ic)) != 1)
9486         return 0;
9487
9488     /* if the size of this greater than one then no
9489        saving */
9490     if (getSize(operandType(IC_RESULT(ic))) > 1)
9491         return 0;
9492
9493     /* otherwise we can save BIG */
9494     lbl = newiTempLabel(NULL);
9495     lbl1= newiTempLabel(NULL);
9496
9497     aopOp(IC_RESULT(ic),ic,FALSE);
9498     
9499     if (IS_AOP_PREG(IC_RESULT(ic))) {
9500         pic14_emitcode("dec","%s",
9501                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9502         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9503         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9504     } else {    
9505
9506
9507       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9508       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9509
9510       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9511       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9512
9513     }
9514 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9515 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9516 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9517 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9518
9519     
9520     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9521     ifx->generated = 1;
9522     return 1;
9523 }
9524
9525 /*-----------------------------------------------------------------*/
9526 /* genReceive - generate code for a receive iCode                  */
9527 /*-----------------------------------------------------------------*/
9528 static void genReceive (iCode *ic)
9529 {    
9530   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9531
9532   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9533       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9534         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9535
9536     int size = getSize(operandType(IC_RESULT(ic)));
9537     int offset =  fReturnSizePic - size;
9538     while (size--) {
9539       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9540                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9541       offset++;
9542     }
9543     aopOp(IC_RESULT(ic),ic,FALSE);  
9544     size = AOP_SIZE(IC_RESULT(ic));
9545     offset = 0;
9546     while (size--) {
9547       pic14_emitcode ("pop","acc");
9548       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9549     }
9550         
9551   } else {
9552     _G.accInUse++;
9553     aopOp(IC_RESULT(ic),ic,FALSE);  
9554     _G.accInUse--;
9555     assignResultValue(IC_RESULT(ic));   
9556   }
9557
9558   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9559 }
9560
9561 /*-----------------------------------------------------------------*/
9562 /* genpic14Code - generate code for pic14 based controllers        */
9563 /*-----------------------------------------------------------------*/
9564 /*
9565  * At this point, ralloc.c has gone through the iCode and attempted
9566  * to optimize in a way suitable for a PIC. Now we've got to generate
9567  * PIC instructions that correspond to the iCode.
9568  *
9569  * Once the instructions are generated, we'll pass through both the
9570  * peep hole optimizer and the pCode optimizer.
9571  *-----------------------------------------------------------------*/
9572
9573 void genpic14Code (iCode *lic)
9574 {
9575     iCode *ic;
9576     int cln = 0;
9577
9578     lineHead = lineCurr = NULL;
9579
9580     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9581     addpBlock(pb);
9582
9583     /* if debug information required */
9584     if (options.debug && currFunc) { 
9585       if (currFunc) {
9586         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9587         _G.debugLine = 1;
9588         if (IS_STATIC(currFunc->etype)) {
9589           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9590           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9591         } else {
9592           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9593           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9594         }
9595         _G.debugLine = 0;
9596       }
9597     }
9598
9599
9600     for (ic = lic ; ic ; ic = ic->next ) {
9601
9602       DEBUGpic14_emitcode(";ic","");
9603         if ( cln != ic->lineno ) {
9604             if ( options.debug ) {
9605                 _G.debugLine = 1;
9606                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9607                          FileBaseName(ic->filename),ic->lineno,
9608                          ic->level,ic->block);
9609                 _G.debugLine = 0;
9610             }
9611             pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9612             pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9613                             printCLine(ic->filename, ic->lineno));
9614
9615             cln = ic->lineno ;
9616         }
9617         /* if the result is marked as
9618            spilt and rematerializable or code for
9619            this has already been generated then
9620            do nothing */
9621         if (resultRemat(ic) || ic->generated ) 
9622             continue ;
9623         
9624         /* depending on the operation */
9625         switch (ic->op) {
9626         case '!' :
9627             genNot(ic);
9628             break;
9629             
9630         case '~' :
9631             genCpl(ic);
9632             break;
9633             
9634         case UNARYMINUS:
9635             genUminus (ic);
9636             break;
9637             
9638         case IPUSH:
9639             genIpush (ic);
9640             break;
9641             
9642         case IPOP:
9643             /* IPOP happens only when trying to restore a 
9644                spilt live range, if there is an ifx statement
9645                following this pop then the if statement might
9646                be using some of the registers being popped which
9647                would destory the contents of the register so
9648                we need to check for this condition and handle it */
9649             if (ic->next            && 
9650                 ic->next->op == IFX &&
9651                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9652                 genIfx (ic->next,ic);
9653             else
9654                 genIpop (ic);
9655             break; 
9656             
9657         case CALL:
9658             genCall (ic);
9659             break;
9660             
9661         case PCALL:
9662             genPcall (ic);
9663             break;
9664             
9665         case FUNCTION:
9666             genFunction (ic);
9667             break;
9668             
9669         case ENDFUNCTION:
9670             genEndFunction (ic);
9671             break;
9672             
9673         case RETURN:
9674             genRet (ic);
9675             break;
9676             
9677         case LABEL:
9678             genLabel (ic);
9679             break;
9680             
9681         case GOTO:
9682             genGoto (ic);
9683             break;
9684             
9685         case '+' :
9686             genPlus (ic) ;
9687             break;
9688             
9689         case '-' :
9690             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9691                 genMinus (ic);
9692             break;
9693             
9694         case '*' :
9695             genMult (ic);
9696             break;
9697             
9698         case '/' :
9699             genDiv (ic) ;
9700             break;
9701             
9702         case '%' :
9703             genMod (ic);
9704             break;
9705             
9706         case '>' :
9707             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9708             break;
9709             
9710         case '<' :
9711             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9712             break;
9713             
9714         case LE_OP:
9715         case GE_OP:
9716         case NE_OP:
9717             
9718             /* note these two are xlated by algebraic equivalence
9719                during parsing SDCC.y */
9720             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9721                    "got '>=' or '<=' shouldn't have come here");
9722             break;      
9723             
9724         case EQ_OP:
9725             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9726             break;          
9727             
9728         case AND_OP:
9729             genAndOp (ic);
9730             break;
9731             
9732         case OR_OP:
9733             genOrOp (ic);
9734             break;
9735             
9736         case '^' :
9737             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9738             break;
9739             
9740         case '|' :
9741                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9742             break;
9743             
9744         case BITWISEAND:
9745             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9746             break;
9747             
9748         case INLINEASM:
9749             genInline (ic);
9750             break;
9751             
9752         case RRC:
9753             genRRC (ic);
9754             break;
9755             
9756         case RLC:
9757             genRLC (ic);
9758             break;
9759             
9760         case GETHBIT:
9761             genGetHbit (ic);
9762             break;
9763             
9764         case LEFT_OP:
9765             genLeftShift (ic);
9766             break;
9767             
9768         case RIGHT_OP:
9769             genRightShift (ic);
9770             break;
9771             
9772         case GET_VALUE_AT_ADDRESS:
9773             genPointerGet(ic);
9774             break;
9775             
9776         case '=' :
9777             if (POINTER_SET(ic))
9778                 genPointerSet(ic);
9779             else
9780                 genAssign(ic);
9781             break;
9782             
9783         case IFX:
9784             genIfx (ic,NULL);
9785             break;
9786             
9787         case ADDRESS_OF:
9788             genAddrOf (ic);
9789             break;
9790             
9791         case JUMPTABLE:
9792             genJumpTab (ic);
9793             break;
9794             
9795         case CAST:
9796             genCast (ic);
9797             break;
9798             
9799         case RECEIVE:
9800             genReceive(ic);
9801             break;
9802             
9803         case SEND:
9804             addSet(&_G.sendSet,ic);
9805             break;
9806
9807         default :
9808             ic = ic;
9809         }
9810     }
9811     
9812
9813     /* now we are ready to call the 
9814        peep hole optimizer */
9815     if (!options.nopeep) {
9816       peepHole (&lineHead);
9817     }
9818     /* now do the actual printing */
9819     printLine (lineHead,codeOutFile);
9820
9821 #ifdef PCODE_DEBUG
9822     DFPRINTF((stderr,"printing pBlock\n\n"));
9823     printpBlock(stdout,pb);
9824 #endif
9825
9826     return;
9827 }