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