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