Numerous bug fixes in PIC Port (pointers, shifting, bank selection,...)
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   SDCCgen51.c - source file for code generation for 8051
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
29                 Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #ifdef HAVE_SYS_ISA_DEFS_H
40 #include <sys/isa_defs.h>
41 #else
42 #ifdef HAVE_MACHINE_ENDIAN_H
43 #include <machine/endian.h>
44 #else
45 #ifdef HAVE_ENDIAN_H
46 #include <endian.h>
47 #else
48 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
49 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
50 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
51 #endif
52 #endif
53 #endif
54 #endif
55
56 #include "common.h"
57 #include "SDCCpeeph.h"
58 #include "ralloc.h"
59 #include "pcode.h"
60 #include "gen.h"
61
62
63 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
64 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
65 void genMult8X8_8 (operand *, operand *,operand *);
66
67 static int labelOffset=0;
68 static int debug_verbose=1;
69 static int optimized_for_speed = 0;
70
71 /* max_key keeps track of the largest label number used in 
72    a function. This is then used to adjust the label offset
73    for the next function.
74 */
75 static int max_key=0;
76 static int GpsuedoStkPtr=0;
77
78 pCodeOp *popGetImmd(char *name, unsigned int offset, int index);
79 unsigned int pic14aopLiteral (value *val, int offset);
80 const char *AopType(short type);
81 static iCode *ifxForOp ( operand *op, iCode *ic );
82
83 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
84
85 /* this is the down and dirty file with all kinds of 
86    kludgy & hacky stuff. This is what it is all about
87    CODE GENERATION for a specific MCU . some of the
88    routines may be reusable, will have to see */
89
90 static char *zero = "#0x00";
91 static char *one  = "#0x01";
92 static char *spname = "sp";
93
94 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
95 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
96 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
97 static char **fReturn = fReturnpic14;
98
99 static char *accUse[] = {"a","b"};
100
101 //static short rbank = -1;
102
103 static struct {
104     short r0Pushed;
105     short r1Pushed;
106     short accInUse;
107     short inLine;
108     short debugLine;
109     short nRegsSaved;
110     set *sendSet;
111 } _G;
112
113 /* Resolved ifx structure. This structure stores information
114    about an iCode ifx that makes it easier to generate code.
115 */
116 typedef struct resolvedIfx {
117   symbol *lbl;     /* pointer to a label */
118   int condition;   /* true or false ifx */
119   int generated;   /* set true when the code associated with the ifx
120                     * is generated */
121 } resolvedIfx;
122
123 extern int pic14_ptrRegReq ;
124 extern int pic14_nRegs;
125 extern FILE *codeOutFile;
126 static void saverbank (int, iCode *,bool);
127
128 static lineNode *lineHead = NULL;
129 static lineNode *lineCurr = NULL;
130
131 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
132 0xE0, 0xC0, 0x80, 0x00};
133 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
134 0x07, 0x03, 0x01, 0x00};
135
136 static  pBlock *pb;
137
138 /*-----------------------------------------------------------------*/
139 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
140 /*                 exponent of 2 is returned, otherwise -1 is      */
141 /*                 returned.                                       */
142 /* note that this is similar to the function `powof2' in SDCCsymt  */
143 /* if(n == 2^y)                                                    */
144 /*   return y;                                                     */
145 /* return -1;                                                      */
146 /*-----------------------------------------------------------------*/
147 static int my_powof2 (unsigned long num)
148 {
149   if(num) {
150     if( (num & (num-1)) == 0) {
151       int nshifts = -1;
152       while(num) {
153         num>>=1;
154         nshifts++;
155       }
156       return nshifts;
157     }
158   }
159
160   return -1;
161 }
162
163 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
164 {
165
166   DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
167                        line_no,
168                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
169                        ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
170                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
171                        ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
172                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
173                        ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
174                        ((result) ? AOP_SIZE(result) : 0));
175
176 }
177
178 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
179 {
180
181   DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
182                        line_no,
183                        ((result) ? AopType(AOP_TYPE(result)) : "-"),
184                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
185                        ((left)   ? AopType(AOP_TYPE(left)) : "-"),
186                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
187                        ((right)  ? AopType(AOP_TYPE(right)) : "-"),
188                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
189
190 }
191
192 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
193 {
194     va_list ap;
195     char lb[INITIAL_INLINEASM];  
196     char *lbp = lb;
197
198     if(!debug_verbose)
199       return;
200
201     va_start(ap,fmt);   
202
203     if (inst && *inst) {
204         if (fmt && *fmt)
205             sprintf(lb,"%s\t",inst);
206         else
207             sprintf(lb,"%s",inst);
208         vsprintf(lb+(strlen(lb)),fmt,ap);
209     }  else
210         vsprintf(lb,fmt,ap);
211
212     while (isspace(*lbp)) lbp++;
213
214     if (lbp && *lbp) 
215         lineCurr = (lineCurr ?
216                     connectLine(lineCurr,newLineNode(lb)) :
217                     (lineHead = newLineNode(lb)));
218     lineCurr->isInline = _G.inLine;
219     lineCurr->isDebug  = _G.debugLine;
220
221     addpCode2pBlock(pb,newpCodeCharP(lb));
222
223     va_end(ap);
224 }
225
226
227 void emitpLabel(int key)
228 {
229   addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
230 }
231
232 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
233 {
234
235   if(pcop)
236     addpCode2pBlock(pb,newpCode(poc,pcop));
237   else
238     DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
239 }
240
241 void emitpcodeNULLop(PIC_OPCODE poc)
242 {
243
244   addpCode2pBlock(pb,newpCode(poc,NULL));
245
246 }
247
248 /*-----------------------------------------------------------------*/
249 /* pic14_emitcode - writes the code into a file : for now it is simple    */
250 /*-----------------------------------------------------------------*/
251 void pic14_emitcode (char *inst,char *fmt, ...)
252 {
253     va_list ap;
254     char lb[INITIAL_INLINEASM];  
255     char *lbp = lb;
256
257     va_start(ap,fmt);   
258
259     if (inst && *inst) {
260         if (fmt && *fmt)
261             sprintf(lb,"%s\t",inst);
262         else
263             sprintf(lb,"%s",inst);
264         vsprintf(lb+(strlen(lb)),fmt,ap);
265     }  else
266         vsprintf(lb,fmt,ap);
267
268     while (isspace(*lbp)) lbp++;
269
270     if (lbp && *lbp) 
271         lineCurr = (lineCurr ?
272                     connectLine(lineCurr,newLineNode(lb)) :
273                     (lineHead = newLineNode(lb)));
274     lineCurr->isInline = _G.inLine;
275     lineCurr->isDebug  = _G.debugLine;
276
277     if(debug_verbose)
278       addpCode2pBlock(pb,newpCodeCharP(lb));
279
280     va_end(ap);
281 }
282
283
284 /*-----------------------------------------------------------------*/
285 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
286 /*-----------------------------------------------------------------*/
287 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
288 {
289     bool r0iu = FALSE , r1iu = FALSE;
290     bool r0ou = FALSE , r1ou = FALSE;
291
292     /* the logic: if r0 & r1 used in the instruction
293     then we are in trouble otherwise */
294
295     /* first check if r0 & r1 are used by this
296     instruction, in which case we are in trouble */
297     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
298         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
299     {
300         goto endOfWorld;      
301     }
302
303     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
304     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
305
306     /* if no usage of r0 then return it */
307     if (!r0iu && !r0ou) {
308         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
309         (*aopp)->type = AOP_R0;
310         
311         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
312     }
313
314     /* if no usage of r1 then return it */
315     if (!r1iu && !r1ou) {
316         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
317         (*aopp)->type = AOP_R1;
318
319         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
320     }    
321
322     /* now we know they both have usage */
323     /* if r0 not used in this instruction */
324     if (!r0iu) {
325         /* push it if not already pushed */
326         if (!_G.r0Pushed) {
327           //pic14_emitcode ("push","%s",
328           //          pic14_regWithIdx(R0_IDX)->dname);
329             _G.r0Pushed++ ;
330         }
331         
332         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
333         (*aopp)->type = AOP_R0;
334
335         return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
336     }
337
338     /* if r1 not used then */
339
340     if (!r1iu) {
341         /* push it if not already pushed */
342         if (!_G.r1Pushed) {
343           //pic14_emitcode ("push","%s",
344           //          pic14_regWithIdx(R1_IDX)->dname);
345             _G.r1Pushed++ ;
346         }
347         
348         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
349         (*aopp)->type = AOP_R1;
350         return pic14_regWithIdx(R1_IDX);
351     }
352
353 endOfWorld :
354     /* I said end of world but not quite end of world yet */
355     /* if this is a result then we can push it on the stack*/
356     if (result) {
357         (*aopp)->type = AOP_STK;    
358         return NULL;
359     }
360
361     /* other wise this is true end of the world */
362     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
363            "getFreePtr should never reach here");
364     exit(0);
365 }
366
367 /*-----------------------------------------------------------------*/
368 /* newAsmop - creates a new asmOp                                  */
369 /*-----------------------------------------------------------------*/
370 asmop *newAsmop (short type)
371 {
372     asmop *aop;
373
374     aop = Safe_calloc(1,sizeof(asmop));
375     aop->type = type;
376     return aop;
377 }
378
379 static void genSetDPTR(int n)
380 {
381     if (!n)
382     {
383         pic14_emitcode(";", "Select standard DPTR");
384         pic14_emitcode("mov", "dps, #0x00");
385     }
386     else
387     {
388         pic14_emitcode(";", "Select alternate DPTR");
389         pic14_emitcode("mov", "dps, #0x01");
390     }
391 }
392
393 /*-----------------------------------------------------------------*/
394 /* resolveIfx - converts an iCode ifx into a form more useful for  */
395 /*              generating code                                    */
396 /*-----------------------------------------------------------------*/
397 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
398 {
399   if(!resIfx) 
400     return;
401
402   DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
403
404   resIfx->condition = 1;    /* assume that the ifx is true */
405   resIfx->generated = 0;    /* indicate that the ifx has not been used */
406
407   if(!ifx) {
408     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
409     DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
410                         __FUNCTION__,__LINE__,resIfx->lbl->key);
411   } else {
412     if(IC_TRUE(ifx)) {
413       resIfx->lbl = IC_TRUE(ifx);
414     } else {
415       resIfx->lbl = IC_FALSE(ifx);
416       resIfx->condition = 0;
417     }
418     if(IC_TRUE(ifx)) 
419       DEBUGpic14_emitcode("; ***","ifx true is non-null");
420     if(IC_FALSE(ifx)) 
421       DEBUGpic14_emitcode("; ***","ifx false is non-null");
422   }
423
424   DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
425
426 }
427 /*-----------------------------------------------------------------*/
428 /* pointerCode - returns the code for a pointer type               */
429 /*-----------------------------------------------------------------*/
430 static int pointerCode (sym_link *etype)
431 {
432
433     return PTR_TYPE(SPEC_OCLS(etype));
434
435 }
436
437 /*-----------------------------------------------------------------*/
438 /* aopForSym - for a true symbol                                   */
439 /*-----------------------------------------------------------------*/
440 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
441 {
442     asmop *aop;
443     memmap *space= SPEC_OCLS(sym->etype);
444
445     DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
446     /* if already has one */
447     if (sym->aop)
448         return sym->aop;
449
450     /* assign depending on the storage class */
451     /* if it is on the stack or indirectly addressable */
452     /* space we need to assign either r0 or r1 to it   */    
453     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
454         sym->aop = aop = newAsmop(0);
455         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
456         aop->size = getSize(sym->type);
457
458         /* now assign the address of the variable to 
459         the pointer register */
460         if (aop->type != AOP_STK) {
461
462             if (sym->onStack) {
463                     if ( _G.accInUse )
464                         pic14_emitcode("push","acc");
465
466                     pic14_emitcode("mov","a,_bp");
467                     pic14_emitcode("add","a,#0x%02x",
468                              ((sym->stack < 0) ?
469                               ((char)(sym->stack - _G.nRegsSaved )) :
470                               ((char)sym->stack)) & 0xff);
471                     pic14_emitcode("mov","%s,a",
472                              aop->aopu.aop_ptr->name);
473
474                     if ( _G.accInUse )
475                         pic14_emitcode("pop","acc");
476             } else
477                 pic14_emitcode("mov","%s,#%s",
478                          aop->aopu.aop_ptr->name,
479                          sym->rname);
480             aop->paged = space->paged;
481         } else
482             aop->aopu.aop_stk = sym->stack;
483         return aop;
484     }
485     
486     if (sym->onStack && options.stack10bit)
487     {
488         /* It's on the 10 bit stack, which is located in
489          * far data space.
490          */
491          
492       //DEBUGpic14_emitcode(";","%d",__LINE__);
493
494         if ( _G.accInUse )
495                 pic14_emitcode("push","acc");
496
497         pic14_emitcode("mov","a,_bp");
498         pic14_emitcode("add","a,#0x%02x",
499                  ((sym->stack < 0) ?
500                    ((char)(sym->stack - _G.nRegsSaved )) :
501                    ((char)sym->stack)) & 0xff);
502         
503         genSetDPTR(1);
504         pic14_emitcode ("mov","dpx1,#0x40");
505         pic14_emitcode ("mov","dph1,#0x00");
506         pic14_emitcode ("mov","dpl1, a");
507         genSetDPTR(0);
508         
509         if ( _G.accInUse )
510             pic14_emitcode("pop","acc");
511             
512         sym->aop = aop = newAsmop(AOP_DPTR2);
513         aop->size = getSize(sym->type); 
514         return aop;
515     }
516
517     //DEBUGpic14_emitcode(";","%d",__LINE__);
518     /* if in bit space */
519     if (IN_BITSPACE(space)) {
520         sym->aop = aop = newAsmop (AOP_CRY);
521         aop->aopu.aop_dir = sym->rname ;
522         aop->size = getSize(sym->type);
523         //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
524         return aop;
525     }
526     /* if it is in direct space */
527     if (IN_DIRSPACE(space)) {
528         sym->aop = aop = newAsmop (AOP_DIR);
529         aop->aopu.aop_dir = sym->rname ;
530         aop->size = getSize(sym->type);
531         DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
532         return aop;
533     }
534
535     /* special case for a function */
536     if (IS_FUNC(sym->type)) {   
537         sym->aop = aop = newAsmop(AOP_IMMD);    
538         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
539         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
540         strcpy(aop->aopu.aop_immd,sym->rname);
541         aop->size = FPTRSIZE; 
542         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
543         return aop;
544     }
545
546
547     /* only remaining is far space */
548     /* in which case DPTR gets the address */
549     sym->aop = aop = newAsmop(AOP_PCODE);
550
551     aop->aopu.pcop = popGetImmd(sym->rname,0,0);
552     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
553     PCOI(aop->aopu.pcop)->index = 0;
554
555     DEBUGpic14_emitcode(";"," rname %s, val %d, const = %d",
556                         sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
557
558     allocDirReg (IC_LEFT(ic));
559
560     aop->size = FPTRSIZE; 
561 /*
562     DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
563     sym->aop = aop = newAsmop(AOP_DPTR);
564     pic14_emitcode ("mov","dptr,#%s", sym->rname);
565     aop->size = getSize(sym->type);
566
567     DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
568 */
569
570     /* if it is in code space */
571     if (IN_CODESPACE(space))
572         aop->code = 1;
573
574     return aop;     
575 }
576
577 /*-----------------------------------------------------------------*/
578 /* aopForRemat - rematerialzes an object                           */
579 /*-----------------------------------------------------------------*/
580 static asmop *aopForRemat (operand *op) // x symbol *sym)
581 {
582   symbol *sym = OP_SYMBOL(op);
583   iCode *ic = NULL;
584   asmop *aop = newAsmop(AOP_PCODE);
585   int val = 0;
586   int offset = 0;
587
588   ic = sym->rematiCode;
589
590     DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
591
592     for (;;) {
593       if (ic->op == '+') {
594         val += (int) operandLitValue(IC_RIGHT(ic));
595       } else if (ic->op == '-') {
596         val -= (int) operandLitValue(IC_RIGHT(ic));
597       } else
598             break;
599         
600         ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
601     }
602
603     offset = OP_SYMBOL(IC_LEFT(ic))->offset;
604     aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
605     PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
606     PCOI(aop->aopu.pcop)->index = val;
607
608     DEBUGpic14_emitcode(";"," rname %s, val %d, const = %d",
609                         OP_SYMBOL(IC_LEFT(ic))->rname,
610                         val, IS_PTR_CONST(operandType(op)));
611
612     //    DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
613
614     allocDirReg (IC_LEFT(ic));
615
616     return aop;        
617 }
618
619 int aopIdx (asmop *aop, int offset)
620 {
621   if(!aop)
622     return -1;
623
624   if(aop->type !=  AOP_REG)
625     return -2;
626         
627   return aop->aopu.aop_reg[offset]->rIdx;
628
629 }
630 /*-----------------------------------------------------------------*/
631 /* regsInCommon - two operands have some registers in common       */
632 /*-----------------------------------------------------------------*/
633 static bool regsInCommon (operand *op1, operand *op2)
634 {
635     symbol *sym1, *sym2;
636     int i;
637
638     /* if they have registers in common */
639     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
640         return FALSE ;
641
642     sym1 = OP_SYMBOL(op1);
643     sym2 = OP_SYMBOL(op2);
644
645     if (sym1->nRegs == 0 || sym2->nRegs == 0)
646         return FALSE ;
647
648     for (i = 0 ; i < sym1->nRegs ; i++) {
649         int j;
650         if (!sym1->regs[i])
651             continue ;
652
653         for (j = 0 ; j < sym2->nRegs ;j++ ) {
654             if (!sym2->regs[j])
655                 continue ;
656
657             if (sym2->regs[j] == sym1->regs[i])
658                 return TRUE ;
659         }
660     }
661
662     return FALSE ;
663 }
664
665 /*-----------------------------------------------------------------*/
666 /* operandsEqu - equivalent                                        */
667 /*-----------------------------------------------------------------*/
668 static bool operandsEqu ( operand *op1, operand *op2)
669 {
670     symbol *sym1, *sym2;
671
672     /* if they not symbols */
673     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
674         return FALSE;
675
676     sym1 = OP_SYMBOL(op1);
677     sym2 = OP_SYMBOL(op2);
678
679     /* if both are itemps & one is spilt
680        and the other is not then false */
681     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
682         sym1->isspilt != sym2->isspilt )
683         return FALSE ;
684
685     /* if they are the same */
686     if (sym1 == sym2)
687         return TRUE ;
688
689     if (strcmp(sym1->rname,sym2->rname) == 0)
690         return TRUE;
691
692
693     /* if left is a tmp & right is not */
694     if (IS_ITEMP(op1)  && 
695         !IS_ITEMP(op2) &&
696         sym1->isspilt  &&
697         (sym1->usl.spillLoc == sym2))
698         return TRUE;
699
700     if (IS_ITEMP(op2)  && 
701         !IS_ITEMP(op1) &&
702         sym2->isspilt  &&
703         sym1->level > 0 &&
704         (sym2->usl.spillLoc == sym1))
705         return TRUE ;
706
707     return FALSE ;
708 }
709
710 /*-----------------------------------------------------------------*/
711 /* pic14_sameRegs - two asmops have the same registers                   */
712 /*-----------------------------------------------------------------*/
713 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
714 {
715     int i;
716
717     if (aop1 == aop2)
718         return TRUE ;
719
720     if (aop1->type != AOP_REG ||
721         aop2->type != AOP_REG )
722         return FALSE ;
723
724     if (aop1->size != aop2->size )
725         return FALSE ;
726
727     for (i = 0 ; i < aop1->size ; i++ )
728         if (aop1->aopu.aop_reg[i] !=
729             aop2->aopu.aop_reg[i] )
730             return FALSE ;
731
732     return TRUE ;
733 }
734
735 /*-----------------------------------------------------------------*/
736 /* aopOp - allocates an asmop for an operand  :                    */
737 /*-----------------------------------------------------------------*/
738 void aopOp (operand *op, iCode *ic, bool result)
739 {
740     asmop *aop;
741     symbol *sym;
742     int i;
743
744     if (!op)
745         return ;
746
747     //    DEBUGpic14_emitcode(";","%d",__LINE__);
748     /* if this a literal */
749     if (IS_OP_LITERAL(op)) {
750         op->aop = aop = newAsmop(AOP_LIT);
751         aop->aopu.aop_lit = op->operand.valOperand;
752         aop->size = getSize(operandType(op));
753         return;
754     }
755
756     {
757       sym_link *type = operandType(op);
758       if(IS_PTR_CONST(type))
759         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
760     }
761
762     /* if already has a asmop then continue */
763     if (op->aop)
764         return ;
765
766     /* if the underlying symbol has a aop */
767     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
768       DEBUGpic14_emitcode(";","%d",__LINE__);
769         op->aop = OP_SYMBOL(op)->aop;
770         return;
771     }
772
773     /* if this is a true symbol */
774     if (IS_TRUE_SYMOP(op)) {    
775       //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
776       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
777       return ;
778     }
779
780     /* this is a temporary : this has
781     only four choices :
782     a) register
783     b) spillocation
784     c) rematerialize 
785     d) conditional   
786     e) can be a return use only */
787
788     sym = OP_SYMBOL(op);
789
790
791     /* if the type is a conditional */
792     if (sym->regType == REG_CND) {
793         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
794         aop->size = 0;
795         return;
796     }
797
798     /* if it is spilt then two situations
799     a) is rematerialize 
800     b) has a spill location */
801     if (sym->isspilt || sym->nRegs == 0) {
802
803       DEBUGpic14_emitcode(";","%d",__LINE__);
804         /* rematerialize it NOW */
805         if (sym->remat) {
806
807             sym->aop = op->aop = aop =
808                                       aopForRemat (op);
809             aop->size = getSize(sym->type);
810             //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
811             return;
812         }
813
814         if (sym->accuse) {
815             int i;
816             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
817             aop->size = getSize(sym->type);
818             for ( i = 0 ; i < 2 ; i++ )
819                 aop->aopu.aop_str[i] = accUse[i];
820             DEBUGpic14_emitcode(";","%d",__LINE__);
821             return;  
822         }
823
824         if (sym->ruonly ) {
825             unsigned i;
826             aop = op->aop = sym->aop = newAsmop(AOP_STR);
827             aop->size = getSize(sym->type);
828             for ( i = 0 ; i < fReturnSizePic ; i++ )
829               aop->aopu.aop_str[i] = fReturn[i];
830             DEBUGpic14_emitcode(";","%d",__LINE__);
831             return;
832         }
833
834         /* else spill location  */
835         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
836             /* force a new aop if sizes differ */
837             sym->usl.spillLoc->aop = NULL;
838         }
839         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
840                             __FUNCTION__,__LINE__,
841                             sym->usl.spillLoc->rname,
842                             sym->rname, sym->usl.spillLoc->offset);
843         // X sym->aop = op->aop = aop = aopForSym(ic,sym->usl.spillLoc,result);
844         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
845         aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
846         //allocDirReg (IC_LEFT(ic));
847         aop->size = getSize(sym->type);
848
849         return;
850     }
851
852     {
853       sym_link *type = operandType(op);
854       if(IS_PTR_CONST(type)) 
855         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
856     }
857
858     /* must be in a register */
859     sym->aop = op->aop = aop = newAsmop(AOP_REG);
860     aop->size = sym->nRegs;
861     for ( i = 0 ; i < sym->nRegs ;i++)
862         aop->aopu.aop_reg[i] = sym->regs[i];
863 }
864
865 /*-----------------------------------------------------------------*/
866 /* freeAsmop - free up the asmop given to an operand               */
867 /*----------------------------------------------------------------*/
868 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
869 {   
870     asmop *aop ;
871
872     if (!op)
873         aop = aaop;
874     else 
875         aop = op->aop;
876
877     if (!aop)
878         return ;
879
880     if (aop->freed)
881         goto dealloc; 
882
883     aop->freed = 1;
884
885     /* depending on the asmop type only three cases need work AOP_RO
886        , AOP_R1 && AOP_STK */
887 #if 0
888     switch (aop->type) {
889         case AOP_R0 :
890             if (_G.r0Pushed ) {
891                 if (pop) {
892                     pic14_emitcode ("pop","ar0");     
893                     _G.r0Pushed--;
894                 }
895             }
896             bitVectUnSetBit(ic->rUsed,R0_IDX);
897             break;
898
899         case AOP_R1 :
900             if (_G.r1Pushed ) {
901                 if (pop) {
902                     pic14_emitcode ("pop","ar1");
903                     _G.r1Pushed--;
904                 }
905             }
906             bitVectUnSetBit(ic->rUsed,R1_IDX);          
907             break;
908
909         case AOP_STK :
910         {
911             int sz = aop->size;    
912             int stk = aop->aopu.aop_stk + aop->size;
913             bitVectUnSetBit(ic->rUsed,R0_IDX);
914             bitVectUnSetBit(ic->rUsed,R1_IDX);          
915
916             getFreePtr(ic,&aop,FALSE);
917             
918             if (options.stack10bit)
919             {
920                 /* I'm not sure what to do here yet... */
921                 /* #STUB */
922                 fprintf(stderr, 
923                         "*** Warning: probably generating bad code for "
924                         "10 bit stack mode.\n");
925             }
926             
927             if (stk) {
928                 pic14_emitcode ("mov","a,_bp");
929                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
930                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
931             } else {
932                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
933             }
934
935             while (sz--) {
936                 pic14_emitcode("pop","acc");
937                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
938                 if (!sz) break;
939                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
940             }
941             op->aop = aop;
942             freeAsmop(op,NULL,ic,TRUE);
943             if (_G.r0Pushed) {
944                 pic14_emitcode("pop","ar0");
945                 _G.r0Pushed--;
946             }
947
948             if (_G.r1Pushed) {
949                 pic14_emitcode("pop","ar1");
950                 _G.r1Pushed--;
951             }       
952         }
953     }
954 #endif
955
956 dealloc:
957     /* all other cases just dealloc */
958     if (op ) {
959         op->aop = NULL;
960         if (IS_SYMOP(op)) {
961             OP_SYMBOL(op)->aop = NULL;    
962             /* if the symbol has a spill */
963             if (SPIL_LOC(op))
964                 SPIL_LOC(op)->aop = NULL;
965         }
966     }
967 }
968
969 /*-----------------------------------------------------------------*/
970 /* aopGet - for fetching value of the aop                          */
971 /*-----------------------------------------------------------------*/
972 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
973 {
974     char *s = buffer ;
975     char *rs;
976
977     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
978     /* offset is greater than
979     size then zero */
980     if (offset > (aop->size - 1) &&
981         aop->type != AOP_LIT)
982         return zero;
983
984     /* depending on type */
985     switch (aop->type) {
986         
987     case AOP_R0:
988     case AOP_R1:
989         DEBUGpic14_emitcode(";","%d",__LINE__);
990         /* if we need to increment it */       
991         while (offset > aop->coff) {        
992             pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
993             aop->coff++;
994         }
995         
996         while (offset < aop->coff) {
997             pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
998             aop->coff--;
999         }
1000         
1001         aop->coff = offset ;
1002         if (aop->paged) {
1003             pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1004             return (dname ? "acc" : "a");
1005         }       
1006         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1007         rs = Safe_calloc(1,strlen(s)+1);
1008         strcpy(rs,s);   
1009         return rs;
1010         
1011     case AOP_DPTR:
1012     case AOP_DPTR2:
1013         DEBUGpic14_emitcode(";","%d",__LINE__);
1014     if (aop->type == AOP_DPTR2)
1015     {
1016         genSetDPTR(1);
1017     }
1018     
1019         while (offset > aop->coff) {
1020             pic14_emitcode ("inc","dptr");
1021             aop->coff++;
1022         }
1023         
1024         while (offset < aop->coff) {        
1025             pic14_emitcode("lcall","__decdptr");
1026             aop->coff--;
1027         }
1028         
1029         aop->coff = offset;
1030         if (aop->code) {
1031             pic14_emitcode("clr","a");
1032             pic14_emitcode("movc","a,@a+dptr");
1033         }
1034     else {
1035             pic14_emitcode("movx","a,@dptr");
1036     }
1037             
1038     if (aop->type == AOP_DPTR2)
1039     {
1040         genSetDPTR(0);
1041     }
1042             
1043     return (dname ? "acc" : "a");
1044         
1045         
1046     case AOP_IMMD:
1047         if (bit16) 
1048             sprintf (s,"%s",aop->aopu.aop_immd);
1049         else
1050             if (offset) 
1051                 sprintf(s,"(%s >> %d)",
1052                         aop->aopu.aop_immd,
1053                         offset*8);
1054             else
1055                 sprintf(s,"%s",
1056                         aop->aopu.aop_immd);
1057         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1058         rs = Safe_calloc(1,strlen(s)+1);
1059         strcpy(rs,s);   
1060         return rs;
1061         
1062     case AOP_DIR:
1063       if (offset) {
1064         sprintf(s,"(%s + %d)",
1065                 aop->aopu.aop_dir,
1066                 offset);
1067         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1068       } else
1069             sprintf(s,"%s",aop->aopu.aop_dir);
1070         rs = Safe_calloc(1,strlen(s)+1);
1071         strcpy(rs,s);   
1072         return rs;
1073         
1074     case AOP_REG:
1075       //if (dname) 
1076       //    return aop->aopu.aop_reg[offset]->dname;
1077       //else
1078             return aop->aopu.aop_reg[offset]->name;
1079         
1080     case AOP_CRY:
1081       //pic14_emitcode(";","%d",__LINE__);
1082       return aop->aopu.aop_dir;
1083         
1084     case AOP_ACC:
1085         DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1086         return "AOP_accumulator_bug";
1087
1088     case AOP_LIT:
1089         sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1090         rs = Safe_calloc(1,strlen(s)+1);
1091         strcpy(rs,s);   
1092         return rs;
1093         
1094     case AOP_STR:
1095         DEBUGpic14_emitcode(";","%d",__LINE__);
1096         aop->coff = offset ;
1097         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1098             dname)
1099             return "acc";
1100         
1101         return aop->aopu.aop_str[offset];
1102         
1103     case AOP_PCODE:
1104       {
1105         pCodeOp *pcop = aop->aopu.pcop;
1106         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE",__LINE__);
1107         if(pcop->name) {
1108           DEBUGpic14_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1109           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1110           sprintf(s,"%s", pcop->name);
1111         } else
1112           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1113
1114       }
1115       rs = Safe_calloc(1,strlen(s)+1);
1116       strcpy(rs,s);   
1117       return rs;
1118
1119     }
1120
1121     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1122            "aopget got unsupported aop->type");
1123     exit(0);
1124 }
1125
1126
1127 /*-----------------------------------------------------------------*/
1128 /* popGetTempReg - create a new temporary pCodeOp                  */
1129 /*-----------------------------------------------------------------*/
1130 pCodeOp *popGetTempReg(void)
1131 {
1132
1133   pCodeOp *pcop;
1134
1135   pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1136   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1137     PCOR(pcop)->r->wasUsed=1;
1138     PCOR(pcop)->r->isFree=0;
1139   }
1140
1141   return pcop;
1142 }
1143
1144 /*-----------------------------------------------------------------*/
1145 /* popGetTempReg - create a new temporary pCodeOp                  */
1146 /*-----------------------------------------------------------------*/
1147 void popReleaseTempReg(pCodeOp *pcop)
1148 {
1149
1150   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1151     PCOR(pcop)->r->isFree = 1;
1152
1153 }
1154 /*-----------------------------------------------------------------*/
1155 /* popGetLabel - create a new pCodeOp of type PO_LABEL             */
1156 /*-----------------------------------------------------------------*/
1157 pCodeOp *popGetLabel(unsigned int key)
1158 {
1159
1160   DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1161
1162   if(key>max_key)
1163     max_key = key;
1164
1165   return newpCodeOpLabel(NULL,key+100+labelOffset);
1166 }
1167
1168 /*-----------------------------------------------------------------*/
1169 /* popCopyReg - copy a pcode operator                              */
1170 /*-----------------------------------------------------------------*/
1171 pCodeOp *popCopyReg(pCodeOpReg *pc)
1172 {
1173   pCodeOpReg *pcor;
1174
1175   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1176   pcor->pcop.type = pc->pcop.type;
1177   if(pc->pcop.name) {
1178     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1179       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1180   } else
1181     pcor->pcop.name = NULL;
1182
1183   pcor->r = pc->r;
1184   pcor->rIdx = pc->rIdx;
1185   pcor->r->wasUsed=1;
1186
1187   //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1188
1189   return PCOP(pcor);
1190 }
1191 /*-----------------------------------------------------------------*/
1192 /* popGet - asm operator to pcode operator conversion              */
1193 /*-----------------------------------------------------------------*/
1194 pCodeOp *popGetLit(unsigned int lit)
1195 {
1196
1197   return newpCodeOpLit(lit);
1198 }
1199
1200
1201 /*-----------------------------------------------------------------*/
1202 /* popGetImmd - asm operator to pcode immediate conversion         */
1203 /*-----------------------------------------------------------------*/
1204 pCodeOp *popGetImmd(char *name, unsigned int offset, int index)
1205 {
1206
1207   return newpCodeOpImmd(name, offset,index, 0);
1208 }
1209
1210
1211 /*-----------------------------------------------------------------*/
1212 /* popGet - asm operator to pcode operator conversion              */
1213 /*-----------------------------------------------------------------*/
1214 pCodeOp *popGetWithString(char *str)
1215 {
1216   pCodeOp *pcop;
1217
1218
1219   if(!str) {
1220     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1221     exit (1);
1222   }
1223
1224   pcop = newpCodeOp(str,PO_STR);
1225
1226   return pcop;
1227 }
1228
1229 pCodeOp *popRegFromString(char *str)
1230 {
1231
1232   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOp) );
1233   pcop->type = PO_DIR;
1234
1235   DEBUGpic14_emitcode(";","%d",__LINE__);
1236   pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1237
1238   return pcop;
1239 }
1240
1241 pCodeOp *popRegFromIdx(int rIdx)
1242 {
1243   pCodeOp *pcop;
1244
1245   DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1246                        __FUNCTION__,__LINE__,rIdx);
1247
1248   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1249
1250   PCOR(pcop)->rIdx = rIdx;
1251   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1252   PCOR(pcop)->r->isFree = 0;
1253   PCOR(pcop)->r->wasUsed = 1;
1254
1255   pcop->type = PCOR(pcop)->r->pc_type;
1256
1257
1258   return pcop;
1259 }
1260 /*-----------------------------------------------------------------*/
1261 /* popGet - asm operator to pcode operator conversion              */
1262 /*-----------------------------------------------------------------*/
1263 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1264 {
1265   //char *s = buffer ;
1266     //char *rs;
1267
1268     pCodeOp *pcop;
1269
1270     //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1271     /* offset is greater than
1272     size then zero */
1273
1274     if (offset > (aop->size - 1) &&
1275         aop->type != AOP_LIT)
1276       return NULL;  //zero;
1277
1278     /* depending on type */
1279     switch (aop->type) {
1280         
1281     case AOP_R0:
1282     case AOP_R1:
1283     case AOP_DPTR:
1284     case AOP_DPTR2:
1285     case AOP_ACC:
1286         DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1287         return NULL;
1288         
1289     case AOP_IMMD:
1290       DEBUGpic14_emitcode(";","%d",__LINE__);
1291       return popGetImmd(aop->aopu.aop_immd,offset,0);
1292
1293     case AOP_DIR:
1294         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1295         pcop->type = PO_DIR;
1296
1297         /*
1298         if (offset)
1299             sprintf(s,"(%s + %d)",
1300                     aop->aopu.aop_dir,
1301                     offset);
1302         else
1303             sprintf(s,"%s",aop->aopu.aop_dir);
1304         pcop->name = Safe_calloc(1,strlen(s)+1);
1305         strcpy(pcop->name,s);   
1306         */
1307         pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1308         strcpy(pcop->name,aop->aopu.aop_dir);   
1309         PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1310         if(PCOR(pcop)->r == NULL) {
1311           //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1312           PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1313         } 
1314
1315       DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1316         PCOR(pcop)->instance = offset;
1317
1318         return pcop;
1319         
1320     case AOP_REG:
1321       {
1322         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1323
1324         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1325         PCOR(pcop)->rIdx = rIdx;
1326         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1327         PCOR(pcop)->instance = offset;
1328         pcop->type = PCOR(pcop)->r->pc_type;
1329         //rs = aop->aopu.aop_reg[offset]->name;
1330         //DEBUGpic14_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1331         return pcop;
1332       }
1333
1334     case AOP_CRY:
1335       pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1336       PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1337       //if(PCOR(pcop)->r == NULL)
1338       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1339       return pcop;
1340         
1341     case AOP_LIT:
1342       return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1343
1344     case AOP_STR:
1345       DEBUGpic14_emitcode(";","%d",__LINE__);
1346       return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1347       /*
1348       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1349       PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1350       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1351       pcop->type = PCOR(pcop)->r->pc_type;
1352       pcop->name = PCOR(pcop)->r->name;
1353
1354       return pcop;
1355       */
1356
1357     case AOP_PCODE:
1358       DEBUGpic14_emitcode(";","popGet AOP_PCODE%d",__LINE__);
1359       pcop = pCodeOpCopy(aop->aopu.pcop);
1360       PCOI(pcop)->offset = offset;
1361       return pcop;
1362     }
1363
1364     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1365            "popGet got unsupported aop->type");
1366     exit(0);
1367 }
1368 /*-----------------------------------------------------------------*/
1369 /* aopPut - puts a string for a aop                                */
1370 /*-----------------------------------------------------------------*/
1371 void aopPut (asmop *aop, char *s, int offset)
1372 {
1373     char *d = buffer ;
1374     symbol *lbl ;
1375
1376     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1377
1378     if (aop->size && offset > ( aop->size - 1)) {
1379         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1380                "aopPut got offset > aop->size");
1381         exit(0);
1382     }
1383
1384     /* will assign value to value */
1385     /* depending on where it is ofcourse */
1386     switch (aop->type) {
1387     case AOP_DIR:
1388       if (offset) {
1389         sprintf(d,"(%s + %d)",
1390                 aop->aopu.aop_dir,offset);
1391         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1392
1393       } else
1394             sprintf(d,"%s",aop->aopu.aop_dir);
1395         
1396         if (strcmp(d,s)) {
1397           DEBUGpic14_emitcode(";","%d",__LINE__);
1398           if(strcmp(s,"W"))
1399             pic14_emitcode("movf","%s,w",s);
1400           pic14_emitcode("movwf","%s",d);
1401
1402           if(strcmp(s,"W")) {
1403             pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1404             if(offset >= aop->size) {
1405               emitpcode(POC_CLRF,popGet(aop,offset));
1406               break;
1407             } else
1408               emitpcode(POC_MOVLW,popGetImmd(s,offset,0));
1409           }
1410
1411           emitpcode(POC_MOVWF,popGet(aop,offset));
1412
1413
1414         }
1415         break;
1416         
1417     case AOP_REG:
1418       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1419         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1420           /*
1421             if (*s == '@'           ||
1422                 strcmp(s,"r0") == 0 ||
1423                 strcmp(s,"r1") == 0 ||
1424                 strcmp(s,"r2") == 0 ||
1425                 strcmp(s,"r3") == 0 ||
1426                 strcmp(s,"r4") == 0 ||
1427                 strcmp(s,"r5") == 0 ||
1428                 strcmp(s,"r6") == 0 || 
1429                 strcmp(s,"r7") == 0 )
1430                 pic14_emitcode("mov","%s,%s  ; %d",
1431                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1432             else
1433           */
1434
1435           if(strcmp(s,"W"))
1436             pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1437
1438           pic14_emitcode("movwf","%s",
1439                    aop->aopu.aop_reg[offset]->name);
1440
1441           if(strcmp(s,"W")) {
1442             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1443             pcop->type = PO_GPR_REGISTER;
1444
1445             PCOR(pcop)->rIdx = -1;
1446             PCOR(pcop)->r = NULL;
1447
1448             DEBUGpic14_emitcode(";","%d",__LINE__);
1449             pcop->name = Safe_strdup(s);
1450             emitpcode(POC_MOVFW,pcop);
1451           }
1452           emitpcode(POC_MOVWF,popGet(aop,offset));
1453
1454         }
1455         break;
1456         
1457     case AOP_DPTR:
1458     case AOP_DPTR2:
1459     
1460     if (aop->type == AOP_DPTR2)
1461     {
1462         genSetDPTR(1);
1463     }
1464     
1465         if (aop->code) {
1466             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1467                    "aopPut writting to code space");
1468             exit(0);
1469         }
1470         
1471         while (offset > aop->coff) {
1472             aop->coff++;
1473             pic14_emitcode ("inc","dptr");
1474         }
1475         
1476         while (offset < aop->coff) {
1477             aop->coff-- ;
1478             pic14_emitcode("lcall","__decdptr");
1479         }
1480         
1481         aop->coff = offset;
1482         
1483         /* if not in accumulater */
1484         MOVA(s);        
1485         
1486         pic14_emitcode ("movx","@dptr,a");
1487         
1488     if (aop->type == AOP_DPTR2)
1489     {
1490         genSetDPTR(0);
1491     }
1492         break;
1493         
1494     case AOP_R0:
1495     case AOP_R1:
1496         while (offset > aop->coff) {
1497             aop->coff++;
1498             pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1499         }
1500         while (offset < aop->coff) {
1501             aop->coff-- ;
1502             pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1503         }
1504         aop->coff = offset;
1505         
1506         if (aop->paged) {
1507             MOVA(s);           
1508             pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1509             
1510         } else
1511             if (*s == '@') {
1512                 MOVA(s);
1513                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1514             } else
1515                 if (strcmp(s,"r0") == 0 ||
1516                     strcmp(s,"r1") == 0 ||
1517                     strcmp(s,"r2") == 0 ||
1518                     strcmp(s,"r3") == 0 ||
1519                     strcmp(s,"r4") == 0 ||
1520                     strcmp(s,"r5") == 0 ||
1521                     strcmp(s,"r6") == 0 || 
1522                     strcmp(s,"r7") == 0 ) {
1523                     char buffer[10];
1524                     sprintf(buffer,"a%s",s);
1525                     pic14_emitcode("mov","@%s,%s",
1526                              aop->aopu.aop_ptr->name,buffer);
1527                 } else
1528                     pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1529         
1530         break;
1531         
1532     case AOP_STK:
1533         if (strcmp(s,"a") == 0)
1534             pic14_emitcode("push","acc");
1535         else
1536             pic14_emitcode("push","%s",s);
1537         
1538         break;
1539         
1540     case AOP_CRY:
1541         /* if bit variable */
1542         if (!aop->aopu.aop_dir) {
1543             pic14_emitcode("clr","a");
1544             pic14_emitcode("rlc","a");
1545         } else {
1546             if (s == zero) 
1547                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1548             else
1549                 if (s == one)
1550                     pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1551                 else
1552                     if (!strcmp(s,"c"))
1553                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1554                     else {
1555                         lbl = newiTempLabel(NULL);
1556                         
1557                         if (strcmp(s,"a")) {
1558                             MOVA(s);
1559                         }
1560                         pic14_emitcode("clr","c");
1561                         pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1562                         pic14_emitcode("cpl","c");
1563                         pic14_emitcode("","%05d_DS_:",lbl->key+100);
1564                         pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1565                     }
1566         }
1567         break;
1568         
1569     case AOP_STR:
1570         aop->coff = offset;
1571         if (strcmp(aop->aopu.aop_str[offset],s))
1572             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1573         break;
1574         
1575     case AOP_ACC:
1576         aop->coff = offset;
1577         if (!offset && (strcmp(s,"acc") == 0))
1578             break;
1579         
1580         if (strcmp(aop->aopu.aop_str[offset],s))
1581             pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1582         break;
1583
1584     default :
1585         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1586                "aopPut got unsupported aop->type");
1587         exit(0);    
1588     }    
1589
1590 }
1591
1592 /*-----------------------------------------------------------------*/
1593 /* reAdjustPreg - points a register back to where it should        */
1594 /*-----------------------------------------------------------------*/
1595 static void reAdjustPreg (asmop *aop)
1596 {
1597     int size ;
1598
1599     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1600     aop->coff = 0;
1601     if ((size = aop->size) <= 1)
1602         return ;
1603     size-- ;
1604     switch (aop->type) {
1605         case AOP_R0 :
1606         case AOP_R1 :
1607             while (size--)
1608                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1609             break;          
1610         case AOP_DPTR :
1611         case AOP_DPTR2:
1612             if (aop->type == AOP_DPTR2)
1613             {
1614                 genSetDPTR(1);
1615             } 
1616             while (size--)
1617             {
1618                 pic14_emitcode("lcall","__decdptr");
1619             }
1620                 
1621             if (aop->type == AOP_DPTR2)
1622             {
1623                 genSetDPTR(0);
1624             }                
1625             break;  
1626
1627     }   
1628
1629 }
1630
1631 /*-----------------------------------------------------------------*/
1632 /* genNotFloat - generates not for float operations              */
1633 /*-----------------------------------------------------------------*/
1634 static void genNotFloat (operand *op, operand *res)
1635 {
1636     int size, offset;
1637     char *l;
1638     symbol *tlbl ;
1639
1640     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1641     /* we will put 127 in the first byte of 
1642     the result */
1643     aopPut(AOP(res),"#127",0);
1644     size = AOP_SIZE(op) - 1;
1645     offset = 1;
1646
1647     l = aopGet(op->aop,offset++,FALSE,FALSE);
1648     MOVA(l);    
1649
1650     while(size--) {
1651         pic14_emitcode("orl","a,%s",
1652                  aopGet(op->aop,
1653                         offset++,FALSE,FALSE));
1654     }
1655     tlbl = newiTempLabel(NULL);
1656
1657     tlbl = newiTempLabel(NULL);
1658     aopPut(res->aop,one,1);
1659     pic14_emitcode("jz","%05d_DS_",(tlbl->key+100));
1660     aopPut(res->aop,zero,1);
1661     pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
1662
1663     size = res->aop->size - 2;
1664     offset = 2;    
1665     /* put zeros in the rest */
1666     while (size--) 
1667         aopPut(res->aop,zero,offset++);
1668 }
1669
1670 #if 0
1671 /*-----------------------------------------------------------------*/
1672 /* opIsGptr: returns non-zero if the passed operand is             */   
1673 /* a generic pointer type.                                         */
1674 /*-----------------------------------------------------------------*/ 
1675 static int opIsGptr(operand *op)
1676 {
1677     sym_link *type = operandType(op);
1678     
1679     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1680     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1681     {
1682         return 1;
1683     }
1684     return 0;        
1685 }
1686 #endif
1687
1688 /*-----------------------------------------------------------------*/
1689 /* pic14_getDataSize - get the operand data size                         */
1690 /*-----------------------------------------------------------------*/
1691 int pic14_getDataSize(operand *op)
1692 {
1693     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1694
1695
1696     return AOP_SIZE(op);
1697
1698     // tsd- in the pic port, the genptr size is 1, so this code here
1699     // fails. ( in the 8051 port, the size was 4).
1700 #if 0
1701     int size;
1702     size = AOP_SIZE(op);
1703     if (size == GPTRSIZE)
1704     {
1705         sym_link *type = operandType(op);
1706         if (IS_GENPTR(type))
1707         {
1708             /* generic pointer; arithmetic operations
1709              * should ignore the high byte (pointer type).
1710              */
1711             size--;
1712     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1713         }
1714     }
1715     return size;
1716 #endif
1717 }
1718
1719 /*-----------------------------------------------------------------*/
1720 /* pic14_outAcc - output Acc                                             */
1721 /*-----------------------------------------------------------------*/
1722 void pic14_outAcc(operand *result)
1723 {
1724   int size,offset;
1725   DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1726   DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1727
1728
1729   size = pic14_getDataSize(result);
1730   if(size){
1731     emitpcode(POC_MOVWF,popGet(AOP(result),0));
1732     size--;
1733     offset = 1;
1734     /* unsigned or positive */
1735     while(size--)
1736       emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1737   }
1738
1739 }
1740
1741 /*-----------------------------------------------------------------*/
1742 /* pic14_outBitC - output a bit C                                        */
1743 /*-----------------------------------------------------------------*/
1744 void pic14_outBitC(operand *result)
1745 {
1746
1747     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1748     /* if the result is bit */
1749     if (AOP_TYPE(result) == AOP_CRY) 
1750         aopPut(AOP(result),"c",0);
1751     else {
1752         pic14_emitcode("clr","a  ; %d", __LINE__);
1753         pic14_emitcode("rlc","a");
1754         pic14_outAcc(result);
1755     }
1756 }
1757
1758 /*-----------------------------------------------------------------*/
1759 /* pic14_toBoolean - emit code for orl a,operator(sizeop)                */
1760 /*-----------------------------------------------------------------*/
1761 void pic14_toBoolean(operand *oper)
1762 {
1763     int size = AOP_SIZE(oper) - 1;
1764     int offset = 1;
1765
1766     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1767
1768     if ( AOP_TYPE(oper) != AOP_ACC) {
1769       emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1770     }
1771     while (size--) {
1772       emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1773     }
1774 }
1775
1776
1777 /*-----------------------------------------------------------------*/
1778 /* genNot - generate code for ! operation                          */
1779 /*-----------------------------------------------------------------*/
1780 static void genNot (iCode *ic)
1781 {
1782   symbol *tlbl;
1783   sym_link *optype = operandType(IC_LEFT(ic));
1784   int size;
1785
1786   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1787   /* assign asmOps to operand & result */
1788   aopOp (IC_LEFT(ic),ic,FALSE);
1789   aopOp (IC_RESULT(ic),ic,TRUE);
1790
1791   DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1792   /* if in bit space then a special case */
1793   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1794     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1795       emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1796       emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1797     } else {
1798       emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1799       emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1800       emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1801     }
1802     goto release;
1803   }
1804
1805   /* if type float then do float */
1806   if (IS_FLOAT(optype)) {
1807     genNotFloat(IC_LEFT(ic),IC_RESULT(ic));
1808     goto release;
1809   }
1810
1811   size = AOP_SIZE(IC_RESULT(ic));
1812   if(size == 1) {
1813     emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1814     emitpcode(POC_ANDLW,popGetLit(1));
1815     emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1816     goto release;
1817   }
1818   pic14_toBoolean(IC_LEFT(ic));
1819
1820   tlbl = newiTempLabel(NULL);
1821   pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1822   pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1823   pic14_outBitC(IC_RESULT(ic));
1824
1825  release:    
1826   /* release the aops */
1827   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1828   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1829 }
1830
1831
1832 /*-----------------------------------------------------------------*/
1833 /* genCpl - generate code for complement                           */
1834 /*-----------------------------------------------------------------*/
1835 static void genCpl (iCode *ic)
1836 {
1837     int offset = 0;
1838     int size ;
1839
1840
1841     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1842     /* assign asmOps to operand & result */
1843     aopOp (IC_LEFT(ic),ic,FALSE);
1844     aopOp (IC_RESULT(ic),ic,TRUE);
1845
1846     /* if both are in bit space then 
1847     a special case */
1848     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1849         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1850
1851         pic14_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
1852         pic14_emitcode("cpl","c"); 
1853         pic14_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
1854         goto release; 
1855     } 
1856
1857     size = AOP_SIZE(IC_RESULT(ic));
1858     while (size--) {
1859         char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
1860         MOVA(l);       
1861         pic14_emitcode("cpl","a");
1862         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1863     }
1864
1865
1866 release:
1867     /* release the aops */
1868     freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1869     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1870 }
1871
1872 /*-----------------------------------------------------------------*/
1873 /* genUminusFloat - unary minus for floating points                */
1874 /*-----------------------------------------------------------------*/
1875 static void genUminusFloat(operand *op,operand *result)
1876 {
1877     int size ,offset =0 ;
1878     char *l;
1879
1880     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1881     /* for this we just need to flip the 
1882     first it then copy the rest in place */
1883     size = AOP_SIZE(op) - 1;
1884     l = aopGet(AOP(op),3,FALSE,FALSE);
1885
1886     MOVA(l);    
1887
1888     pic14_emitcode("cpl","acc.7");
1889     aopPut(AOP(result),"a",3);    
1890
1891     while(size--) {
1892         aopPut(AOP(result),
1893                aopGet(AOP(op),offset,FALSE,FALSE),
1894                offset);
1895         offset++;
1896     }          
1897 }
1898
1899 /*-----------------------------------------------------------------*/
1900 /* genUminus - unary minus code generation                         */
1901 /*-----------------------------------------------------------------*/
1902 static void genUminus (iCode *ic)
1903 {
1904   int size, i;
1905   sym_link *optype, *rtype;
1906
1907
1908   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1909   /* assign asmops */
1910   aopOp(IC_LEFT(ic),ic,FALSE);
1911   aopOp(IC_RESULT(ic),ic,TRUE);
1912
1913   /* if both in bit space then special
1914      case */
1915   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1916       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
1917
1918     emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0));
1919     emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
1920     emitpcode(POC_BSF,   popGet(AOP(IC_RESULT(ic)),0));
1921
1922     goto release; 
1923   } 
1924
1925   optype = operandType(IC_LEFT(ic));
1926   rtype = operandType(IC_RESULT(ic));
1927
1928   /* if float then do float stuff */
1929   if (IS_FLOAT(optype)) {
1930     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
1931     goto release;
1932   }
1933
1934   /* otherwise subtract from zero by taking the 2's complement */
1935   size = AOP_SIZE(IC_LEFT(ic));
1936
1937   for(i=0; i<size; i++) {
1938     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1939       emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
1940     else {
1941       emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
1942       emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
1943     }
1944   }
1945
1946   emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
1947   for(i=1; i<size; i++) {
1948     emitSKPNZ;
1949     emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
1950   }
1951
1952  release:
1953   /* release the aops */
1954   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1955   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
1956 }
1957
1958 /*-----------------------------------------------------------------*/
1959 /* saveRegisters - will look for a call and save the registers     */
1960 /*-----------------------------------------------------------------*/
1961 static void saveRegisters(iCode *lic) 
1962 {
1963     int i;
1964     iCode *ic;
1965     bitVect *rsave;
1966     sym_link *dtype;
1967
1968     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1969     /* look for call */
1970     for (ic = lic ; ic ; ic = ic->next) 
1971         if (ic->op == CALL || ic->op == PCALL)
1972             break;
1973
1974     if (!ic) {
1975         fprintf(stderr,"found parameter push with no function call\n");
1976         return ;
1977     }
1978
1979     /* if the registers have been saved already then
1980     do nothing */
1981     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
1982         return ;
1983
1984     /* find the registers in use at this time 
1985     and push them away to safety */
1986     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
1987                           ic->rUsed);
1988
1989     ic->regsSaved = 1;
1990     if (options.useXstack) {
1991         if (bitVectBitValue(rsave,R0_IDX))
1992             pic14_emitcode("mov","b,r0");
1993         pic14_emitcode("mov","r0,%s",spname);
1994         for (i = 0 ; i < pic14_nRegs ; i++) {
1995             if (bitVectBitValue(rsave,i)) {
1996                 if (i == R0_IDX)
1997                     pic14_emitcode("mov","a,b");
1998                 else
1999                     pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2000                 pic14_emitcode("movx","@r0,a");
2001                 pic14_emitcode("inc","r0");
2002             }
2003         }
2004         pic14_emitcode("mov","%s,r0",spname);
2005         if (bitVectBitValue(rsave,R0_IDX))
2006             pic14_emitcode("mov","r0,b");           
2007     }// else
2008     //for (i = 0 ; i < pic14_nRegs ; i++) {
2009     //    if (bitVectBitValue(rsave,i))
2010     //  pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2011     //}
2012
2013     dtype = operandType(IC_LEFT(ic));
2014     if (currFunc && dtype && 
2015         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2016         IFFUNC_ISISR(currFunc->type) &&
2017         !ic->bankSaved) 
2018
2019         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2020
2021 }
2022 /*-----------------------------------------------------------------*/
2023 /* unsaveRegisters - pop the pushed registers                      */
2024 /*-----------------------------------------------------------------*/
2025 static void unsaveRegisters (iCode *ic)
2026 {
2027     int i;
2028     bitVect *rsave;
2029
2030     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2031     /* find the registers in use at this time 
2032     and push them away to safety */
2033     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2034                           ic->rUsed);
2035     
2036     if (options.useXstack) {
2037         pic14_emitcode("mov","r0,%s",spname);   
2038         for (i =  pic14_nRegs ; i >= 0 ; i--) {
2039             if (bitVectBitValue(rsave,i)) {
2040                 pic14_emitcode("dec","r0");
2041                 pic14_emitcode("movx","a,@r0");
2042                 if (i == R0_IDX)
2043                     pic14_emitcode("mov","b,a");
2044                 else
2045                     pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2046             }       
2047
2048         }
2049         pic14_emitcode("mov","%s,r0",spname);
2050         if (bitVectBitValue(rsave,R0_IDX))
2051             pic14_emitcode("mov","r0,b");
2052     } //else
2053     //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2054     //    if (bitVectBitValue(rsave,i))
2055     //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2056     //}
2057
2058 }  
2059
2060
2061 /*-----------------------------------------------------------------*/
2062 /* pushSide -                                                      */
2063 /*-----------------------------------------------------------------*/
2064 static void pushSide(operand * oper, int size)
2065 {
2066 #if 0
2067         int offset = 0;
2068     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2069         while (size--) {
2070                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2071                 if (AOP_TYPE(oper) != AOP_REG &&
2072                     AOP_TYPE(oper) != AOP_DIR &&
2073                     strcmp(l,"a") ) {
2074                         pic14_emitcode("mov","a,%s",l);
2075                         pic14_emitcode("push","acc");
2076                 } else
2077                         pic14_emitcode("push","%s",l);
2078         }
2079 #endif
2080 }
2081
2082 /*-----------------------------------------------------------------*/
2083 /* assignResultValue -                                             */
2084 /*-----------------------------------------------------------------*/
2085 static void assignResultValue(operand * oper)
2086 {
2087   int size = AOP_SIZE(oper);
2088
2089   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2090
2091   DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2092
2093   if(!GpsuedoStkPtr) {
2094     /* The last byte in the assignment is in W */
2095     size--;
2096     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2097     GpsuedoStkPtr++;
2098   }
2099
2100   while (size--) {
2101     emitpcode(POC_MOVFW,popRegFromIdx(GpsuedoStkPtr-1 + Gstack_base_addr));
2102     GpsuedoStkPtr++;
2103     emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2104   }
2105 }
2106
2107
2108 /*-----------------------------------------------------------------*/
2109 /* genIpush - genrate code for pushing this gets a little complex  */
2110 /*-----------------------------------------------------------------*/
2111 static void genIpush (iCode *ic)
2112 {
2113
2114   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2115 #if 0
2116     int size, offset = 0 ;
2117     char *l;
2118
2119
2120     /* if this is not a parm push : ie. it is spill push 
2121     and spill push is always done on the local stack */
2122     if (!ic->parmPush) {
2123
2124         /* and the item is spilt then do nothing */
2125         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2126             return ;
2127
2128         aopOp(IC_LEFT(ic),ic,FALSE);
2129         size = AOP_SIZE(IC_LEFT(ic));
2130         /* push it on the stack */
2131         while(size--) {
2132             l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2133             if (*l == '#') {
2134                 MOVA(l);
2135                 l = "acc";
2136             }
2137             pic14_emitcode("push","%s",l);
2138         }
2139         return ;        
2140     }
2141
2142     /* this is a paramter push: in this case we call
2143     the routine to find the call and save those
2144     registers that need to be saved */   
2145     saveRegisters(ic);
2146
2147     /* then do the push */
2148     aopOp(IC_LEFT(ic),ic,FALSE);
2149
2150
2151         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2152     size = AOP_SIZE(IC_LEFT(ic));
2153
2154     while (size--) {
2155         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2156         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2157             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2158             strcmp(l,"a") ) {
2159             pic14_emitcode("mov","a,%s",l);
2160             pic14_emitcode("push","acc");
2161         } else
2162             pic14_emitcode("push","%s",l);
2163     }       
2164
2165     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2166 #endif
2167 }
2168
2169 /*-----------------------------------------------------------------*/
2170 /* genIpop - recover the registers: can happen only for spilling   */
2171 /*-----------------------------------------------------------------*/
2172 static void genIpop (iCode *ic)
2173 {
2174   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2175 #if 0
2176     int size,offset ;
2177
2178
2179     /* if the temp was not pushed then */
2180     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2181         return ;
2182
2183     aopOp(IC_LEFT(ic),ic,FALSE);
2184     size = AOP_SIZE(IC_LEFT(ic));
2185     offset = (size-1);
2186     while (size--) 
2187         pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2188                                    FALSE,TRUE));
2189
2190     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2191 #endif
2192 }
2193
2194 /*-----------------------------------------------------------------*/
2195 /* unsaverbank - restores the resgister bank from stack            */
2196 /*-----------------------------------------------------------------*/
2197 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2198 {
2199   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2200 #if 0
2201     int i;
2202     asmop *aop ;
2203     regs *r = NULL;
2204
2205     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2206     if (popPsw) {
2207         if (options.useXstack) {
2208             aop = newAsmop(0);
2209             r = getFreePtr(ic,&aop,FALSE);
2210             
2211             
2212             pic14_emitcode("mov","%s,_spx",r->name);
2213             pic14_emitcode("movx","a,@%s",r->name);
2214             pic14_emitcode("mov","psw,a");
2215             pic14_emitcode("dec","%s",r->name);
2216             
2217         }else
2218             pic14_emitcode ("pop","psw");
2219     }
2220
2221     for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2222         if (options.useXstack) {       
2223             pic14_emitcode("movx","a,@%s",r->name);
2224             //pic14_emitcode("mov","(%s+%d),a",
2225             //       regspic14[i].base,8*bank+regspic14[i].offset);
2226             pic14_emitcode("dec","%s",r->name);
2227
2228         } else 
2229           pic14_emitcode("pop",""); //"(%s+%d)",
2230         //regspic14[i].base,8*bank); //+regspic14[i].offset);
2231     }
2232
2233     if (options.useXstack) {
2234
2235         pic14_emitcode("mov","_spx,%s",r->name);
2236         freeAsmop(NULL,aop,ic,TRUE);
2237
2238     }
2239 #endif 
2240 }
2241
2242 /*-----------------------------------------------------------------*/
2243 /* saverbank - saves an entire register bank on the stack          */
2244 /*-----------------------------------------------------------------*/
2245 static void saverbank (int bank, iCode *ic, bool pushPsw)
2246 {
2247   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2248 #if 0
2249     int i;
2250     asmop *aop ;
2251     regs *r = NULL;
2252
2253     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2254     if (options.useXstack) {
2255
2256         aop = newAsmop(0);
2257         r = getFreePtr(ic,&aop,FALSE);  
2258         pic14_emitcode("mov","%s,_spx",r->name);
2259
2260     }
2261
2262     for (i = 0 ; i < pic14_nRegs ;i++) {
2263         if (options.useXstack) {
2264             pic14_emitcode("inc","%s",r->name);
2265             //pic14_emitcode("mov","a,(%s+%d)",
2266             //         regspic14[i].base,8*bank+regspic14[i].offset);
2267             pic14_emitcode("movx","@%s,a",r->name);           
2268         } else 
2269           pic14_emitcode("push","");// "(%s+%d)",
2270                      //regspic14[i].base,8*bank+regspic14[i].offset);
2271     }
2272     
2273     if (pushPsw) {
2274         if (options.useXstack) {
2275             pic14_emitcode("mov","a,psw");
2276             pic14_emitcode("movx","@%s,a",r->name);     
2277             pic14_emitcode("inc","%s",r->name);
2278             pic14_emitcode("mov","_spx,%s",r->name);       
2279             freeAsmop (NULL,aop,ic,TRUE);
2280             
2281         } else
2282             pic14_emitcode("push","psw");
2283         
2284         pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2285     }
2286     ic->bankSaved = 1;
2287 #endif
2288 }
2289
2290 /*-----------------------------------------------------------------*/
2291 /* genCall - generates a call statement                            */
2292 /*-----------------------------------------------------------------*/
2293 static void genCall (iCode *ic)
2294 {
2295   sym_link *dtype;   
2296
2297   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2298
2299   /* if caller saves & we have not saved then */
2300   if (!ic->regsSaved)
2301     saveRegisters(ic);
2302
2303   /* if we are calling a function that is not using
2304      the same register bank then we need to save the
2305      destination registers on the stack */
2306   dtype = operandType(IC_LEFT(ic));
2307   if (currFunc && dtype && 
2308       (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2309       IFFUNC_ISISR(currFunc->type) &&
2310       !ic->bankSaved) 
2311
2312     saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2313
2314   /* if send set is not empty the assign */
2315   if (_G.sendSet) {
2316     iCode *sic;
2317     /* For the Pic port, there is no data stack.
2318      * So parameters passed to functions are stored
2319      * in registers. (The pCode optimizer will get
2320      * rid of most of these :).
2321      */
2322     int psuedoStkPtr=-1; 
2323     int firstTimeThruLoop = 1;
2324
2325     _G.sendSet = reverseSet(_G.sendSet);
2326
2327     /* First figure how many parameters are getting passed */
2328     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2329          sic = setNextItem(_G.sendSet)) {
2330
2331       aopOp(IC_LEFT(sic),sic,FALSE);
2332       psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2333       freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2334     }
2335
2336     for (sic = setFirstItem(_G.sendSet) ; sic ; 
2337          sic = setNextItem(_G.sendSet)) {
2338       int size, offset = 0;
2339
2340       aopOp(IC_LEFT(sic),sic,FALSE);
2341       size = AOP_SIZE(IC_LEFT(sic));
2342
2343
2344       while (size--) {
2345         DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2346                              AopType(AOP_TYPE(IC_LEFT(sic))));
2347
2348         if(!firstTimeThruLoop) {
2349           /* If this is not the first time we've been through the loop
2350            * then we need to save the parameter in a temporary
2351            * register. The last byte of the last parameter is
2352            * passed in W. */
2353           emitpcode(POC_MOVWF,popRegFromIdx(--psuedoStkPtr + Gstack_base_addr));
2354
2355         }
2356         firstTimeThruLoop=0;
2357
2358         //if (strcmp(l,fReturn[offset])) {
2359
2360         if ( ((AOP(IC_LEFT(sic))->type) == AOP_PCODE) ||
2361              ((AOP(IC_LEFT(sic))->type) == AOP_LIT) )
2362           emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(sic)),offset));
2363         else
2364           emitpcode(POC_MOVFW,popGet(AOP(IC_LEFT(sic)),offset));
2365
2366         //}
2367         offset++;
2368       }
2369       freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2370     }
2371     _G.sendSet = NULL;
2372   }
2373   /* make the call */
2374   emitpcode(POC_CALL,popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2375                                       OP_SYMBOL(IC_LEFT(ic))->rname :
2376                                       OP_SYMBOL(IC_LEFT(ic))->name));
2377
2378   GpsuedoStkPtr=0;
2379   /* if we need assign a result value */
2380   if ((IS_ITEMP(IC_RESULT(ic)) && 
2381        (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2382         OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2383       IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2384
2385     _G.accInUse++;
2386     aopOp(IC_RESULT(ic),ic,FALSE);
2387     _G.accInUse--;
2388
2389     assignResultValue(IC_RESULT(ic));
2390
2391     DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2392                          AopType(AOP_TYPE(IC_RESULT(ic))));
2393                 
2394     freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2395   }
2396
2397   /* adjust the stack for parameters if 
2398      required */
2399   if (ic->parmBytes) {
2400     int i;
2401     if (ic->parmBytes > 3) {
2402       pic14_emitcode("mov","a,%s",spname);
2403       pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2404       pic14_emitcode("mov","%s,a",spname);
2405     } else 
2406       for ( i = 0 ; i <  ic->parmBytes ;i++)
2407         pic14_emitcode("dec","%s",spname);
2408
2409   }
2410
2411   /* if register bank was saved then pop them */
2412   if (ic->bankSaved)
2413     unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2414
2415   /* if we hade saved some registers then unsave them */
2416   if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2417     unsaveRegisters (ic);
2418
2419
2420 }
2421
2422 /*-----------------------------------------------------------------*/
2423 /* genPcall - generates a call by pointer statement                */
2424 /*-----------------------------------------------------------------*/
2425 static void genPcall (iCode *ic)
2426 {
2427     sym_link *dtype;
2428     symbol *rlbl = newiTempLabel(NULL);
2429
2430
2431     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2432     /* if caller saves & we have not saved then */
2433     if (!ic->regsSaved)
2434         saveRegisters(ic);
2435
2436     /* if we are calling a function that is not using
2437     the same register bank then we need to save the
2438     destination registers on the stack */
2439     dtype = operandType(IC_LEFT(ic));
2440     if (currFunc && dtype && 
2441         IFFUNC_ISISR(currFunc->type) &&
2442         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2443         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2444
2445
2446     /* push the return address on to the stack */
2447     pic14_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2448     pic14_emitcode("push","acc");    
2449     pic14_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2450     pic14_emitcode("push","acc");
2451     
2452     if (options.model == MODEL_FLAT24)
2453     {
2454         pic14_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2455         pic14_emitcode("push","acc");    
2456     }
2457
2458     /* now push the calling address */
2459     aopOp(IC_LEFT(ic),ic,FALSE);
2460
2461     pushSide(IC_LEFT(ic), FPTRSIZE);
2462
2463     freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2464
2465     /* if send set is not empty the assign */
2466     if (_G.sendSet) {
2467         iCode *sic ;
2468
2469         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2470              sic = setNextItem(_G.sendSet)) {
2471             int size, offset = 0;
2472             aopOp(IC_LEFT(sic),sic,FALSE);
2473             size = AOP_SIZE(IC_LEFT(sic));
2474             while (size--) {
2475                 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
2476                                 FALSE,FALSE);
2477                 if (strcmp(l,fReturn[offset]))
2478                     pic14_emitcode("mov","%s,%s",
2479                              fReturn[offset],
2480                              l);
2481                 offset++;
2482             }
2483             freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2484         }
2485         _G.sendSet = NULL;
2486     }
2487
2488     pic14_emitcode("ret","");
2489     pic14_emitcode("","%05d_DS_:",(rlbl->key+100));
2490
2491
2492     /* if we need assign a result value */
2493     if ((IS_ITEMP(IC_RESULT(ic)) &&
2494          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2495           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2496         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2497
2498         _G.accInUse++;
2499         aopOp(IC_RESULT(ic),ic,FALSE);
2500         _G.accInUse--;
2501         
2502         assignResultValue(IC_RESULT(ic));
2503
2504         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2505     }
2506
2507     /* adjust the stack for parameters if 
2508     required */
2509     if (ic->parmBytes) {
2510         int i;
2511         if (ic->parmBytes > 3) {
2512             pic14_emitcode("mov","a,%s",spname);
2513             pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2514             pic14_emitcode("mov","%s,a",spname);
2515         } else 
2516             for ( i = 0 ; i <  ic->parmBytes ;i++)
2517                 pic14_emitcode("dec","%s",spname);
2518
2519     }
2520
2521     /* if register bank was saved then unsave them */
2522     if (currFunc && dtype && 
2523         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2524         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2525
2526     /* if we hade saved some registers then
2527     unsave them */
2528     if (ic->regsSaved)
2529         unsaveRegisters (ic);
2530
2531 }
2532
2533 /*-----------------------------------------------------------------*/
2534 /* resultRemat - result  is rematerializable                       */
2535 /*-----------------------------------------------------------------*/
2536 static int resultRemat (iCode *ic)
2537 {
2538     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2539     if (SKIP_IC(ic) || ic->op == IFX)
2540         return 0;
2541
2542     if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2543         symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2544         if (sym->remat && !POINTER_SET(ic)) 
2545             return 1;
2546     }
2547
2548     return 0;
2549 }
2550
2551 #if defined(__BORLANDC__) || defined(_MSC_VER)
2552 #define STRCASECMP stricmp
2553 #else
2554 #define STRCASECMP strcasecmp
2555 #endif
2556
2557 #if 0
2558 /*-----------------------------------------------------------------*/
2559 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2560 /*-----------------------------------------------------------------*/
2561 static bool inExcludeList(char *s)
2562 {
2563   DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2564     int i =0;
2565     
2566     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2567     if (options.excludeRegs[i] &&
2568     STRCASECMP(options.excludeRegs[i],"none") == 0)
2569         return FALSE ;
2570
2571     for ( i = 0 ; options.excludeRegs[i]; i++) {
2572         if (options.excludeRegs[i] &&
2573         STRCASECMP(s,options.excludeRegs[i]) == 0)
2574             return TRUE;
2575     }
2576     return FALSE ;
2577 }
2578 #endif
2579
2580 /*-----------------------------------------------------------------*/
2581 /* genFunction - generated code for function entry                 */
2582 /*-----------------------------------------------------------------*/
2583 static void genFunction (iCode *ic)
2584 {
2585     symbol *sym;
2586     sym_link *ftype;
2587
2588     DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2589
2590     labelOffset += (max_key+4);
2591     max_key=0;
2592     GpsuedoStkPtr=0;
2593     _G.nRegsSaved = 0;
2594     /* create the function header */
2595     pic14_emitcode(";","-----------------------------------------");
2596     pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2597     pic14_emitcode(";","-----------------------------------------");
2598
2599     pic14_emitcode("","%s:",sym->rname);
2600     addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname));
2601
2602     ftype = operandType(IC_LEFT(ic));
2603
2604     /* if critical function then turn interrupts off */
2605     if (IFFUNC_ISCRITICAL(ftype))
2606         pic14_emitcode("clr","ea");
2607
2608     /* here we need to generate the equates for the
2609        register bank if required */
2610 #if 0
2611     if (FUNC_REGBANK(ftype) != rbank) {
2612         int i ;
2613
2614         rbank = FUNC_REGBANK(ftype);
2615         for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2616             if (strcmp(regspic14[i].base,"0") == 0)
2617                 pic14_emitcode("","%s = 0x%02x",
2618                          regspic14[i].dname,
2619                          8*rbank+regspic14[i].offset);
2620             else
2621                 pic14_emitcode ("","%s = %s + 0x%02x",
2622                           regspic14[i].dname,
2623                           regspic14[i].base,
2624                           8*rbank+regspic14[i].offset);
2625         }
2626     }
2627 #endif
2628
2629     /* if this is an interrupt service routine then
2630     save acc, b, dpl, dph  */
2631     if (IFFUNC_ISISR(sym->type)) {
2632       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2633       emitpcodeNULLop(POC_NOP);
2634       emitpcodeNULLop(POC_NOP);
2635       emitpcodeNULLop(POC_NOP);
2636       emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2637       emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2638       emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2639       emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2640
2641       pBlockConvert2ISR(pb);
2642 #if 0  
2643         if (!inExcludeList("acc"))          
2644             pic14_emitcode ("push","acc");      
2645         if (!inExcludeList("b"))
2646             pic14_emitcode ("push","b");
2647         if (!inExcludeList("dpl"))
2648             pic14_emitcode ("push","dpl");
2649         if (!inExcludeList("dph"))
2650             pic14_emitcode ("push","dph");
2651         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2652         {
2653             pic14_emitcode ("push", "dpx");
2654             /* Make sure we're using standard DPTR */
2655             pic14_emitcode ("push", "dps");
2656             pic14_emitcode ("mov", "dps, #0x00");
2657             if (options.stack10bit)
2658             {   
2659                 /* This ISR could conceivably use DPTR2. Better save it. */
2660                 pic14_emitcode ("push", "dpl1");
2661                 pic14_emitcode ("push", "dph1");
2662                 pic14_emitcode ("push", "dpx1");
2663             }
2664         }
2665         /* if this isr has no bank i.e. is going to
2666            run with bank 0 , then we need to save more
2667            registers :-) */
2668         if (!FUNC_REGBANK(sym->type)) {
2669
2670             /* if this function does not call any other
2671                function then we can be economical and
2672                save only those registers that are used */
2673             if (! IFFUNC_HASFCALL(sym->type)) {
2674                 int i;
2675
2676                 /* if any registers used */
2677                 if (sym->regsUsed) {
2678                     /* save the registers used */
2679                     for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2680                         if (bitVectBitValue(sym->regsUsed,i) ||
2681                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2682                           pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);                         
2683                     }
2684                 }
2685                 
2686             } else {
2687                 /* this function has  a function call cannot
2688                    determines register usage so we will have the
2689                    entire bank */
2690                 saverbank(0,ic,FALSE);
2691             }       
2692         }
2693 #endif
2694     } else {
2695         /* if callee-save to be used for this function
2696            then save the registers being used in this function */
2697         if (IFFUNC_CALLEESAVES(sym->type)) {
2698             int i;
2699             
2700             /* if any registers used */
2701             if (sym->regsUsed) {
2702                 /* save the registers used */
2703                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2704                     if (bitVectBitValue(sym->regsUsed,i) ||
2705                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2706                       //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2707                         _G.nRegsSaved++;
2708                     }
2709                 }
2710             }
2711         }
2712     }
2713
2714     /* set the register bank to the desired value */
2715     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2716         pic14_emitcode("push","psw");
2717         pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);   
2718     }
2719
2720     if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2721
2722         if (options.useXstack) {
2723             pic14_emitcode("mov","r0,%s",spname);
2724             pic14_emitcode("mov","a,_bp");
2725             pic14_emitcode("movx","@r0,a");
2726             pic14_emitcode("inc","%s",spname);
2727         }
2728         else
2729         {
2730             /* set up the stack */
2731             pic14_emitcode ("push","_bp");     /* save the callers stack  */
2732         }
2733         pic14_emitcode ("mov","_bp,%s",spname);
2734     }
2735
2736     /* adjust the stack for the function */
2737     if (sym->stack) {
2738
2739         int i = sym->stack;
2740         if (i > 256 ) 
2741             werror(W_STACK_OVERFLOW,sym->name);
2742
2743         if (i > 3 && sym->recvSize < 4) {              
2744
2745             pic14_emitcode ("mov","a,sp");
2746             pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2747             pic14_emitcode ("mov","sp,a");
2748            
2749         }
2750         else
2751             while(i--)
2752                 pic14_emitcode("inc","sp");
2753     }
2754
2755      if (sym->xstack) {
2756
2757         pic14_emitcode ("mov","a,_spx");
2758         pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2759         pic14_emitcode ("mov","_spx,a");
2760     }    
2761
2762 }
2763
2764 /*-----------------------------------------------------------------*/
2765 /* genEndFunction - generates epilogue for functions               */
2766 /*-----------------------------------------------------------------*/
2767 static void genEndFunction (iCode *ic)
2768 {
2769     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2770
2771     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2772
2773     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2774     {
2775         pic14_emitcode ("mov","%s,_bp",spname);
2776     }
2777
2778     /* if use external stack but some variables were
2779     added to the local stack then decrement the
2780     local stack */
2781     if (options.useXstack && sym->stack) {      
2782         pic14_emitcode("mov","a,sp");
2783         pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2784         pic14_emitcode("mov","sp,a");
2785     }
2786
2787
2788     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2789         if (options.useXstack) {
2790             pic14_emitcode("mov","r0,%s",spname);
2791             pic14_emitcode("movx","a,@r0");
2792             pic14_emitcode("mov","_bp,a");
2793             pic14_emitcode("dec","%s",spname);
2794         }
2795         else
2796         {
2797             pic14_emitcode ("pop","_bp");
2798         }
2799     }
2800
2801     /* restore the register bank  */    
2802     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2803         pic14_emitcode ("pop","psw");
2804
2805     if (IFFUNC_ISISR(sym->type)) {
2806
2807         /* now we need to restore the registers */
2808         /* if this isr has no bank i.e. is going to
2809            run with bank 0 , then we need to save more
2810            registers :-) */
2811         if (!FUNC_REGBANK(sym->type)) {
2812             
2813             /* if this function does not call any other
2814                function then we can be economical and
2815                save only those registers that are used */
2816             if (! IFFUNC_HASFCALL(sym->type)) {
2817                 int i;
2818                 
2819                 /* if any registers used */
2820                 if (sym->regsUsed) {
2821                     /* save the registers used */
2822                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2823                         if (bitVectBitValue(sym->regsUsed,i) ||
2824                           (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2825                           pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2826                     }
2827                 }
2828                 
2829             } else {
2830                 /* this function has  a function call cannot
2831                    determines register usage so we will have the
2832                    entire bank */
2833                 unsaverbank(0,ic,FALSE);
2834             }       
2835         }
2836 #if 0
2837         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2838         {
2839             if (options.stack10bit)
2840             {
2841                 pic14_emitcode ("pop", "dpx1");
2842                 pic14_emitcode ("pop", "dph1");
2843                 pic14_emitcode ("pop", "dpl1");
2844             }   
2845             pic14_emitcode ("pop", "dps");
2846             pic14_emitcode ("pop", "dpx");
2847         }
2848         if (!inExcludeList("dph"))
2849             pic14_emitcode ("pop","dph");
2850         if (!inExcludeList("dpl"))
2851             pic14_emitcode ("pop","dpl");
2852         if (!inExcludeList("b"))
2853             pic14_emitcode ("pop","b");
2854         if (!inExcludeList("acc"))
2855             pic14_emitcode ("pop","acc");
2856
2857         if (IFFUNC_ISCRITICAL(sym->type))
2858             pic14_emitcode("setb","ea");
2859 #endif
2860
2861         /* if debug then send end of function */
2862 /*      if (options.debug && currFunc) { */
2863         if (currFunc) {
2864             _G.debugLine = 1;
2865             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2866                      FileBaseName(ic->filename),currFunc->lastLine,
2867                      ic->level,ic->block); 
2868             if (IS_STATIC(currFunc->etype))         
2869                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2870             else
2871                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2872             _G.debugLine = 0;
2873         }
2874         
2875         pic14_emitcode ("reti","");
2876
2877         emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2878         emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2879         emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2880         emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2881         emitpcode(POC_MOVFW,  popCopyReg(&pc_wsave));
2882         addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2883
2884         emitpcodeNULLop(POC_RETFIE);
2885
2886     }
2887     else {
2888         if (IFFUNC_ISCRITICAL(sym->type))
2889             pic14_emitcode("setb","ea");
2890         
2891         if (IFFUNC_CALLEESAVES(sym->type)) {
2892             int i;
2893             
2894             /* if any registers used */
2895             if (sym->regsUsed) {
2896                 /* save the registers used */
2897                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2898                     if (bitVectBitValue(sym->regsUsed,i) ||
2899                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2900                       pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2901                 }
2902             }
2903             
2904         }
2905
2906         /* if debug then send end of function */
2907         if (currFunc) {
2908             _G.debugLine = 1;
2909             pic14_emitcode(";","C$%s$%d$%d$%d ==.",
2910                      FileBaseName(ic->filename),currFunc->lastLine,
2911                      ic->level,ic->block); 
2912             if (IS_STATIC(currFunc->etype))         
2913                 pic14_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
2914             else
2915                 pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
2916             _G.debugLine = 0;
2917         }
2918
2919         pic14_emitcode ("return","");
2920         emitpcodeNULLop(POC_RETURN);
2921
2922         /* Mark the end of a function */
2923         addpCode2pBlock(pb,newpCodeFunction(NULL,NULL));
2924     }
2925
2926 }
2927
2928 /*-----------------------------------------------------------------*/
2929 /* genRet - generate code for return statement                     */
2930 /*-----------------------------------------------------------------*/
2931 static void genRet (iCode *ic)
2932 {
2933   int size,offset = 0 , pushed = 0;
2934     
2935   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2936   /* if we have no return value then
2937      just generate the "ret" */
2938   if (!IC_LEFT(ic)) 
2939     goto jumpret;       
2940     
2941   /* we have something to return then
2942      move the return value into place */
2943   aopOp(IC_LEFT(ic),ic,FALSE);
2944   size = AOP_SIZE(IC_LEFT(ic));
2945     
2946   while (size--) {
2947     char *l ;
2948     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
2949       /* #NOCHANGE */
2950       l = aopGet(AOP(IC_LEFT(ic)),offset++,
2951                  FALSE,TRUE);
2952       pic14_emitcode("push","%s",l);
2953       pushed++;
2954     } else {
2955       l = aopGet(AOP(IC_LEFT(ic)),offset,
2956                  FALSE,FALSE);
2957       if (strcmp(fReturn[offset],l)) {
2958         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
2959             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
2960           emitpcode(POC_MOVLW, popGet(AOP(IC_LEFT(ic)),offset));
2961         }else {
2962           emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
2963         }
2964         if(size) {
2965           emitpcode(POC_MOVWF,popRegFromIdx(offset + Gstack_base_addr));
2966           pic14_emitcode("movwf","%s",fReturn[offset]);
2967         }
2968         offset++;
2969       }
2970     }
2971   }    
2972
2973   if (pushed) {
2974     while(pushed) {
2975       pushed--;
2976       if (strcmp(fReturn[pushed],"a"))
2977         pic14_emitcode("pop",fReturn[pushed]);
2978       else
2979         pic14_emitcode("pop","acc");
2980     }
2981   }
2982   freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2983     
2984  jumpret:
2985   /* generate a jump to the return label
2986      if the next is not the return statement */
2987   if (!(ic->next && ic->next->op == LABEL &&
2988         IC_LABEL(ic->next) == returnLabel)) {
2989         
2990     emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
2991     pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
2992   }
2993     
2994 }
2995
2996 /*-----------------------------------------------------------------*/
2997 /* genLabel - generates a label                                    */
2998 /*-----------------------------------------------------------------*/
2999 static void genLabel (iCode *ic)
3000 {
3001     /* special case never generate */
3002     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3003     if (IC_LABEL(ic) == entryLabel)
3004         return ;
3005
3006     emitpLabel(IC_LABEL(ic)->key);
3007     pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3008 }
3009
3010 /*-----------------------------------------------------------------*/
3011 /* genGoto - generates a goto                                      */
3012 /*-----------------------------------------------------------------*/
3013 //tsd
3014 static void genGoto (iCode *ic)
3015 {
3016   emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3017   pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3018 }
3019
3020
3021 /*-----------------------------------------------------------------*/
3022 /* genMultbits :- multiplication of bits                           */
3023 /*-----------------------------------------------------------------*/
3024 static void genMultbits (operand *left, 
3025                          operand *right, 
3026                          operand *result)
3027 {
3028   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3029
3030   if(!pic14_sameRegs(AOP(result),AOP(right)))
3031     emitpcode(POC_BSF,  popGet(AOP(result),0));
3032
3033   emitpcode(POC_BTFSC,popGet(AOP(right),0));
3034   emitpcode(POC_BTFSS,popGet(AOP(left),0));
3035   emitpcode(POC_BCF,  popGet(AOP(result),0));
3036
3037 }
3038
3039
3040 /*-----------------------------------------------------------------*/
3041 /* genMultOneByte : 8 bit multiplication & division                */
3042 /*-----------------------------------------------------------------*/
3043 static void genMultOneByte (operand *left,
3044                             operand *right,
3045                             operand *result)
3046 {
3047   sym_link *opetype = operandType(result);
3048
3049   // symbol *lbl ;
3050   int size,offset;
3051
3052   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3053   DEBUGpic14_AopType(__LINE__,left,right,result);
3054   DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3055
3056   /* (if two literals, the value is computed before) */
3057   /* if one literal, literal on the right */
3058   if (AOP_TYPE(left) == AOP_LIT){
3059     operand *t = right;
3060     right = left;
3061     left = t;
3062   }
3063
3064   size = AOP_SIZE(result);
3065   if(size == 1) {
3066
3067     if (AOP_TYPE(right) == AOP_LIT){
3068       pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3069                      aopGet(AOP(right),0,FALSE,FALSE), 
3070                      aopGet(AOP(left),0,FALSE,FALSE), 
3071                      aopGet(AOP(result),0,FALSE,FALSE));
3072       pic14_emitcode("call","genMultLit");
3073     } else {
3074       pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3075                      aopGet(AOP(right),0,FALSE,FALSE), 
3076                      aopGet(AOP(left),0,FALSE,FALSE), 
3077                      aopGet(AOP(result),0,FALSE,FALSE));
3078       pic14_emitcode("call","genMult8X8_8");
3079
3080     }
3081     genMult8X8_8 (left, right,result);
3082
3083
3084     /* signed or unsigned */
3085     //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3086     //l = aopGet(AOP(left),0,FALSE,FALSE);
3087     //MOVA(l);       
3088     //pic14_emitcode("mul","ab");
3089     /* if result size = 1, mul signed = mul unsigned */
3090     //aopPut(AOP(result),"a",0);
3091
3092   } else {  // (size > 1)
3093
3094     pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3095                    aopGet(AOP(right),0,FALSE,FALSE), 
3096                    aopGet(AOP(left),0,FALSE,FALSE), 
3097                    aopGet(AOP(result),0,FALSE,FALSE));
3098
3099     if (SPEC_USIGN(opetype)){
3100       pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3101       genUMult8X8_16 (left, right, result, NULL);
3102
3103       if (size > 2) {
3104         /* for filling the MSBs */
3105         emitpcode(POC_CLRF,  popGet(AOP(result),2));
3106         emitpcode(POC_CLRF,  popGet(AOP(result),3));
3107       }
3108     }
3109     else{
3110       pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3111
3112       pic14_emitcode("mov","a,b");
3113
3114       /* adjust the MSB if left or right neg */
3115
3116       /* if one literal */
3117       if (AOP_TYPE(right) == AOP_LIT){
3118         pic14_emitcode("multiply ","right is a lit");
3119         /* AND literal negative */
3120         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3121           /* adjust MSB (c==0 after mul) */
3122           pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3123         }
3124       }
3125       else{
3126         genSMult8X8_16 (left, right, result, NULL);
3127       }
3128
3129       if(size > 2){
3130         pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3131         /* get the sign */
3132         pic14_emitcode("rlc","a");
3133         pic14_emitcode("subb","a,acc");
3134       }
3135     }
3136
3137     size -= 2;   
3138     offset = 2;
3139     if (size > 0)
3140       while (size--)
3141         pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3142     //aopPut(AOP(result),"a",offset++);
3143   }
3144 }
3145
3146 /*-----------------------------------------------------------------*/
3147 /* genMult - generates code for multiplication                     */
3148 /*-----------------------------------------------------------------*/
3149 static void genMult (iCode *ic)
3150 {
3151     operand *left = IC_LEFT(ic);
3152     operand *right = IC_RIGHT(ic);
3153     operand *result= IC_RESULT(ic);   
3154
3155     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3156     /* assign the amsops */
3157     aopOp (left,ic,FALSE);
3158     aopOp (right,ic,FALSE);
3159     aopOp (result,ic,TRUE);
3160
3161   DEBUGpic14_AopType(__LINE__,left,right,result);
3162
3163     /* special cases first */
3164     /* both are bits */
3165     if (AOP_TYPE(left) == AOP_CRY &&
3166         AOP_TYPE(right)== AOP_CRY) {
3167         genMultbits(left,right,result);
3168         goto release ;
3169     }
3170
3171     /* if both are of size == 1 */
3172     if (AOP_SIZE(left) == 1 &&
3173         AOP_SIZE(right) == 1 ) {
3174         genMultOneByte(left,right,result);
3175         goto release ;
3176     }
3177
3178     pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3179
3180     /* should have been converted to function call */
3181     //assert(0) ;
3182
3183 release :
3184     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3185     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3186     freeAsmop(result,NULL,ic,TRUE); 
3187 }
3188
3189 /*-----------------------------------------------------------------*/
3190 /* genDivbits :- division of bits                                  */
3191 /*-----------------------------------------------------------------*/
3192 static void genDivbits (operand *left, 
3193                         operand *right, 
3194                         operand *result)
3195 {
3196
3197     char *l;
3198
3199     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3200     /* the result must be bit */    
3201     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3202     l = aopGet(AOP(left),0,FALSE,FALSE);
3203
3204     MOVA(l);    
3205
3206     pic14_emitcode("div","ab");
3207     pic14_emitcode("rrc","a");
3208     aopPut(AOP(result),"c",0);
3209 }
3210
3211 /*-----------------------------------------------------------------*/
3212 /* genDivOneByte : 8 bit division                                  */
3213 /*-----------------------------------------------------------------*/
3214 static void genDivOneByte (operand *left,
3215                            operand *right,
3216                            operand *result)
3217 {
3218     sym_link *opetype = operandType(result);
3219     char *l ;
3220     symbol *lbl ;
3221     int size,offset;
3222
3223     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3224     size = AOP_SIZE(result) - 1;
3225     offset = 1;
3226     /* signed or unsigned */
3227     if (SPEC_USIGN(opetype)) {
3228         /* unsigned is easy */
3229         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3230         l = aopGet(AOP(left),0,FALSE,FALSE);
3231         MOVA(l);        
3232         pic14_emitcode("div","ab");
3233         aopPut(AOP(result),"a",0);
3234         while (size--)
3235             aopPut(AOP(result),zero,offset++);
3236         return ;
3237     }
3238
3239     /* signed is a little bit more difficult */
3240
3241     /* save the signs of the operands */
3242     l = aopGet(AOP(left),0,FALSE,FALSE);    
3243     MOVA(l);    
3244     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3245     pic14_emitcode("push","acc"); /* save it on the stack */
3246
3247     /* now sign adjust for both left & right */
3248     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3249     MOVA(l);       
3250     lbl = newiTempLabel(NULL);
3251     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3252     pic14_emitcode("cpl","a");   
3253     pic14_emitcode("inc","a");
3254     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3255     pic14_emitcode("mov","b,a");
3256
3257     /* sign adjust left side */
3258     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3259     MOVA(l);
3260
3261     lbl = newiTempLabel(NULL);
3262     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3263     pic14_emitcode("cpl","a");
3264     pic14_emitcode("inc","a");
3265     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3266
3267     /* now the division */
3268     pic14_emitcode("div","ab");
3269     /* we are interested in the lower order
3270     only */
3271     pic14_emitcode("mov","b,a");
3272     lbl = newiTempLabel(NULL);
3273     pic14_emitcode("pop","acc");   
3274     /* if there was an over flow we don't 
3275     adjust the sign of the result */
3276     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3277     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3278     CLRC;
3279     pic14_emitcode("clr","a");
3280     pic14_emitcode("subb","a,b");
3281     pic14_emitcode("mov","b,a");
3282     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3283
3284     /* now we are done */
3285     aopPut(AOP(result),"b",0);
3286     if(size > 0){
3287         pic14_emitcode("mov","c,b.7");
3288         pic14_emitcode("subb","a,acc");   
3289     }
3290     while (size--)
3291         aopPut(AOP(result),"a",offset++);
3292
3293 }
3294
3295 /*-----------------------------------------------------------------*/
3296 /* genDiv - generates code for division                            */
3297 /*-----------------------------------------------------------------*/
3298 static void genDiv (iCode *ic)
3299 {
3300     operand *left = IC_LEFT(ic);
3301     operand *right = IC_RIGHT(ic);
3302     operand *result= IC_RESULT(ic);   
3303
3304     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3305     /* assign the amsops */
3306     aopOp (left,ic,FALSE);
3307     aopOp (right,ic,FALSE);
3308     aopOp (result,ic,TRUE);
3309
3310     /* special cases first */
3311     /* both are bits */
3312     if (AOP_TYPE(left) == AOP_CRY &&
3313         AOP_TYPE(right)== AOP_CRY) {
3314         genDivbits(left,right,result);
3315         goto release ;
3316     }
3317
3318     /* if both are of size == 1 */
3319     if (AOP_SIZE(left) == 1 &&
3320         AOP_SIZE(right) == 1 ) {
3321         genDivOneByte(left,right,result);
3322         goto release ;
3323     }
3324
3325     /* should have been converted to function call */
3326     assert(0);
3327 release :
3328     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3329     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3330     freeAsmop(result,NULL,ic,TRUE); 
3331 }
3332
3333 /*-----------------------------------------------------------------*/
3334 /* genModbits :- modulus of bits                                   */
3335 /*-----------------------------------------------------------------*/
3336 static void genModbits (operand *left, 
3337                         operand *right, 
3338                         operand *result)
3339 {
3340
3341     char *l;
3342
3343     /* the result must be bit */    
3344     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3345     l = aopGet(AOP(left),0,FALSE,FALSE);
3346
3347     MOVA(l);       
3348
3349     pic14_emitcode("div","ab");
3350     pic14_emitcode("mov","a,b");
3351     pic14_emitcode("rrc","a");
3352     aopPut(AOP(result),"c",0);
3353 }
3354
3355 /*-----------------------------------------------------------------*/
3356 /* genModOneByte : 8 bit modulus                                   */
3357 /*-----------------------------------------------------------------*/
3358 static void genModOneByte (operand *left,
3359                            operand *right,
3360                            operand *result)
3361 {
3362     sym_link *opetype = operandType(result);
3363     char *l ;
3364     symbol *lbl ;
3365
3366     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3367     /* signed or unsigned */
3368     if (SPEC_USIGN(opetype)) {
3369         /* unsigned is easy */
3370         pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3371         l = aopGet(AOP(left),0,FALSE,FALSE);
3372         MOVA(l);    
3373         pic14_emitcode("div","ab");
3374         aopPut(AOP(result),"b",0);
3375         return ;
3376     }
3377
3378     /* signed is a little bit more difficult */
3379
3380     /* save the signs of the operands */
3381     l = aopGet(AOP(left),0,FALSE,FALSE);    
3382     MOVA(l);
3383
3384     pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3385     pic14_emitcode("push","acc"); /* save it on the stack */
3386
3387     /* now sign adjust for both left & right */
3388     l =  aopGet(AOP(right),0,FALSE,FALSE);    
3389     MOVA(l);
3390
3391     lbl = newiTempLabel(NULL);
3392     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3393     pic14_emitcode("cpl","a");   
3394     pic14_emitcode("inc","a");
3395     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3396     pic14_emitcode("mov","b,a"); 
3397
3398     /* sign adjust left side */
3399     l =  aopGet(AOP(left),0,FALSE,FALSE);    
3400     MOVA(l);
3401
3402     lbl = newiTempLabel(NULL);
3403     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3404     pic14_emitcode("cpl","a");   
3405     pic14_emitcode("inc","a");
3406     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3407
3408     /* now the multiplication */
3409     pic14_emitcode("div","ab");
3410     /* we are interested in the lower order
3411     only */
3412     lbl = newiTempLabel(NULL);
3413     pic14_emitcode("pop","acc");   
3414     /* if there was an over flow we don't 
3415     adjust the sign of the result */
3416     pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3417     pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3418     CLRC ;
3419     pic14_emitcode("clr","a");
3420     pic14_emitcode("subb","a,b");
3421     pic14_emitcode("mov","b,a");
3422     pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3423
3424     /* now we are done */
3425     aopPut(AOP(result),"b",0);
3426
3427 }
3428
3429 /*-----------------------------------------------------------------*/
3430 /* genMod - generates code for division                            */
3431 /*-----------------------------------------------------------------*/
3432 static void genMod (iCode *ic)
3433 {
3434     operand *left = IC_LEFT(ic);
3435     operand *right = IC_RIGHT(ic);
3436     operand *result= IC_RESULT(ic);  
3437
3438     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3439     /* assign the amsops */
3440     aopOp (left,ic,FALSE);
3441     aopOp (right,ic,FALSE);
3442     aopOp (result,ic,TRUE);
3443
3444     /* special cases first */
3445     /* both are bits */
3446     if (AOP_TYPE(left) == AOP_CRY &&
3447         AOP_TYPE(right)== AOP_CRY) {
3448         genModbits(left,right,result);
3449         goto release ;
3450     }
3451
3452     /* if both are of size == 1 */
3453     if (AOP_SIZE(left) == 1 &&
3454         AOP_SIZE(right) == 1 ) {
3455         genModOneByte(left,right,result);
3456         goto release ;
3457     }
3458
3459     /* should have been converted to function call */
3460     assert(0);
3461
3462 release :
3463     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3464     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3465     freeAsmop(result,NULL,ic,TRUE); 
3466 }
3467
3468 /*-----------------------------------------------------------------*/
3469 /* genIfxJump :- will create a jump depending on the ifx           */
3470 /*-----------------------------------------------------------------*/
3471 /*
3472   note: May need to add parameter to indicate when a variable is in bit space.
3473 */
3474 static void genIfxJump (iCode *ic, char *jval)
3475 {
3476
3477     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3478     /* if true label then we jump if condition
3479     supplied is true */
3480     if ( IC_TRUE(ic) ) {
3481
3482         if(strcmp(jval,"a") == 0)
3483           emitSKPZ;
3484         else if (strcmp(jval,"c") == 0)
3485           emitSKPC;
3486         else {
3487           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3488           emitpcode(POC_BTFSC,  newpCodeOpBit(jval,-1,1));
3489         }
3490
3491         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3492         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3493
3494     }
3495     else {
3496         /* false label is present */
3497         if(strcmp(jval,"a") == 0)
3498           emitSKPNZ;
3499         else if (strcmp(jval,"c") == 0)
3500           emitSKPNC;
3501         else {
3502           DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3503           emitpcode(POC_BTFSS,  newpCodeOpBit(jval,-1,1));
3504         }
3505
3506         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3507         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3508
3509     }
3510
3511
3512     /* mark the icode as generated */
3513     ic->generated = 1;
3514 }
3515
3516 /*-----------------------------------------------------------------*/
3517 /* genSkip                                                         */
3518 /*-----------------------------------------------------------------*/
3519 static void genSkip(iCode *ifx,int status_bit)
3520 {
3521   if(!ifx)
3522     return;
3523
3524   if ( IC_TRUE(ifx) ) {
3525     switch(status_bit) {
3526     case 'z':
3527       emitSKPNZ;
3528       break;
3529
3530     case 'c':
3531       emitSKPNC;
3532       break;
3533
3534     case 'd':
3535       emitSKPDC;
3536       break;
3537
3538     }
3539
3540     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3541     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3542
3543   } else {
3544
3545     switch(status_bit) {
3546
3547     case 'z':
3548       emitSKPZ;
3549       break;
3550
3551     case 'c':
3552       emitSKPC;
3553       break;
3554
3555     case 'd':
3556       emitSKPDC;
3557       break;
3558     }
3559     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3560     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3561
3562   }
3563
3564 }
3565
3566 /*-----------------------------------------------------------------*/
3567 /* genSkipc                                                        */
3568 /*-----------------------------------------------------------------*/
3569 static void genSkipc(resolvedIfx *rifx)
3570 {
3571   if(!rifx)
3572     return;
3573
3574   if(rifx->condition)
3575     emitSKPC;
3576   else
3577     emitSKPNC;
3578
3579   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3580   rifx->generated = 1;
3581 }
3582
3583 /*-----------------------------------------------------------------*/
3584 /* genSkipz2                                                       */
3585 /*-----------------------------------------------------------------*/
3586 static void genSkipz2(resolvedIfx *rifx)
3587 {
3588   if(!rifx)
3589     return;
3590
3591   if(rifx->condition)
3592     emitSKPZ;
3593   else
3594     emitSKPNZ;
3595
3596   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3597   rifx->generated = 1;
3598 }
3599
3600 /*-----------------------------------------------------------------*/
3601 /* genSkipz                                                        */
3602 /*-----------------------------------------------------------------*/
3603 static void genSkipz(iCode *ifx, int condition)
3604 {
3605   if(!ifx)
3606     return;
3607
3608   if(condition)
3609     emitSKPNZ;
3610   else
3611     emitSKPZ;
3612
3613   if ( IC_TRUE(ifx) )
3614     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3615   else
3616     emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3617
3618   if ( IC_TRUE(ifx) )
3619     pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3620   else
3621     pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3622
3623 }
3624 /*-----------------------------------------------------------------*/
3625 /* genSkipCond                                                     */
3626 /*-----------------------------------------------------------------*/
3627 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3628 {
3629   if(!rifx)
3630     return;
3631
3632   if(rifx->condition)
3633     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3634   else
3635     emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3636
3637
3638   emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3639   rifx->generated = 1;
3640 }
3641
3642 #if 0
3643 /*-----------------------------------------------------------------*/
3644 /* genChkZeroes :- greater or less than comparison                 */
3645 /*     For each byte in a literal that is zero, inclusive or the   */
3646 /*     the corresponding byte in the operand with W                */
3647 /*     returns true if any of the bytes are zero                   */
3648 /*-----------------------------------------------------------------*/
3649 static int genChkZeroes(operand *op, int lit,  int size)
3650 {
3651
3652   int i;
3653   int flag =1;
3654
3655   while(size--) {
3656     i = (lit >> (size*8)) & 0xff;
3657
3658     if(i==0) {
3659       if(flag) 
3660         emitpcode(POC_MOVFW, popGet(AOP(op),size));
3661       else
3662         emitpcode(POC_IORFW, popGet(AOP(op),size));
3663       flag = 0;
3664     }
3665   }
3666
3667   return (flag==0);
3668 }
3669 #endif
3670
3671 /*-----------------------------------------------------------------*/
3672 /* genCmp :- greater or less than comparison                       */
3673 /*-----------------------------------------------------------------*/
3674 static void genCmp (operand *left,operand *right,
3675                     operand *result, iCode *ifx, int sign)
3676 {
3677   int size; //, offset = 0 ;
3678   unsigned long lit = 0L,i = 0;
3679   resolvedIfx rFalseIfx;
3680   //  resolvedIfx rTrueIfx;
3681   symbol *truelbl;
3682   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3683   if(ifx) {
3684   DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3685   DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3686   }
3687
3688
3689   resolveIfx(&rFalseIfx,ifx);
3690   truelbl  = newiTempLabel(NULL);
3691
3692   //if(IC_TRUE(ifx) == NULL)
3693   /* if left & right are bit variables */
3694   if (AOP_TYPE(left) == AOP_CRY &&
3695       AOP_TYPE(right) == AOP_CRY ) {
3696     pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3697     pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3698   } else {
3699     /* subtract right from left if at the
3700        end the carry flag is set then we know that
3701        left is greater than right */
3702     size = max(AOP_SIZE(left),AOP_SIZE(right));
3703
3704     /* if unsigned char cmp with lit, do cjne left,#right,zz */
3705     //if((size == 1) && !sign &&
3706     //   (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
3707     //  symbol *lbl  = newiTempLabel(NULL);
3708     //  pic14_emitcode("cjne","%s,%s,%05d_DS_",
3709     //       aopGet(AOP(left),offset,FALSE,FALSE),
3710     //       aopGet(AOP(right),offset,FALSE,FALSE),
3711     //       lbl->key+100);
3712     //pic14_emitcode("","%05d_DS_:",lbl->key+100);
3713     //} else 
3714       {
3715
3716       symbol *lbl  = newiTempLabel(NULL);
3717
3718       if(AOP_TYPE(right) == AOP_LIT) {
3719
3720         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3721
3722         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3723
3724         /* special cases */
3725
3726         if(lit == 0) {
3727
3728           if(sign != 0) 
3729             genSkipCond(&rFalseIfx,left,size-1,7);
3730           else 
3731             /* no need to compare to 0...*/
3732             /* NOTE: this is a de-generate compare that most certainly 
3733              *       creates some dead code. */
3734             emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3735
3736           if(ifx) ifx->generated = 1;
3737           return;
3738
3739         }
3740         size--;
3741
3742         if(size == 0) {
3743           //i = (lit >> (size*8)) & 0xff;
3744           DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3745         
3746           emitpcode(POC_MOVFW, popGet(AOP(left),size));
3747
3748           i = ((0-lit) & 0xff);
3749           if(sign) {
3750             if( i == 0x81) { 
3751               /* lit is 0x7f, all signed chars are less than
3752                * this except for 0x7f itself */
3753               emitpcode(POC_XORLW, popGetLit(0x7f));
3754               genSkipz2(&rFalseIfx);
3755             } else {
3756               emitpcode(POC_ADDLW, popGetLit(0x80));
3757               emitpcode(POC_ADDLW, popGetLit(i^0x80));
3758               genSkipc(&rFalseIfx);
3759             }
3760
3761           } else {
3762             emitpcode(POC_ADDLW, popGetLit(i));
3763             genSkipc(&rFalseIfx);
3764
3765           }
3766
3767           if(ifx) ifx->generated = 1;
3768           return;
3769         }
3770
3771         /* chars are out of the way. now do ints and longs */
3772
3773
3774         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3775         
3776         /* special cases */
3777
3778         if(sign) {
3779
3780           if(lit == 0) {
3781             genSkipCond(&rFalseIfx,left,size,7);
3782             if(ifx) ifx->generated = 1;
3783             return;
3784           }
3785
3786           if(lit <0x100) {
3787             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3788
3789             //rFalseIfx.condition ^= 1;
3790             //genSkipCond(&rFalseIfx,left,size,7);
3791             //rFalseIfx.condition ^= 1;
3792
3793             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3794             if(rFalseIfx.condition)
3795               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3796             else
3797               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3798
3799             emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3800             emitpcode(POC_ADDFW, popGet(AOP(left),0));
3801             emitpcode(POC_MOVFW, popGet(AOP(left),1));
3802
3803             while(size > 1)
3804               emitpcode(POC_IORFW, popGet(AOP(left),size--));
3805
3806             if(rFalseIfx.condition) {
3807               emitSKPZ;
3808               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3809
3810             } else {
3811               emitSKPNZ;
3812             }
3813
3814             genSkipc(&rFalseIfx);
3815             emitpLabel(truelbl->key);
3816             if(ifx) ifx->generated = 1;
3817             return;
3818
3819           }
3820
3821           if(size == 1) {
3822
3823             if( (lit & 0xff) == 0) {
3824               /* lower byte is zero */
3825               DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3826               i = ((lit >> 8) & 0xff) ^0x80;
3827               emitpcode(POC_MOVFW, popGet(AOP(left),size));
3828               emitpcode(POC_ADDLW, popGetLit( 0x80));
3829               emitpcode(POC_ADDLW, popGetLit(0x100-i));
3830               genSkipc(&rFalseIfx);
3831
3832
3833               if(ifx) ifx->generated = 1;
3834               return;
3835
3836             }
3837           } else {
3838             /* Special cases for signed longs */
3839             if( (lit & 0xffffff) == 0) {
3840               /* lower byte is zero */
3841               DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3842               i = ((lit >> 8*3) & 0xff) ^0x80;
3843               emitpcode(POC_MOVFW, popGet(AOP(left),size));
3844               emitpcode(POC_ADDLW, popGetLit( 0x80));
3845               emitpcode(POC_ADDLW, popGetLit(0x100-i));
3846               genSkipc(&rFalseIfx);
3847
3848
3849               if(ifx) ifx->generated = 1;
3850               return;
3851
3852             }
3853
3854           }
3855
3856
3857           if(lit & (0x80 << (size*8))) {
3858             /* lit is negative */
3859             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3860
3861             //genSkipCond(&rFalseIfx,left,size,7);
3862
3863             emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3864
3865             if(rFalseIfx.condition)
3866               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3867             else
3868               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3869
3870
3871           } else {
3872             /* lit is positive */
3873             DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3874             emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3875             if(rFalseIfx.condition)
3876               emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3877             else
3878               emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3879
3880             //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3881             //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3882             //rFalseIfx.condition ^= 1;
3883             //genSkipCond(&rFalseIfx,left,size,7);
3884             //rFalseIfx.condition ^= 1;
3885           }
3886
3887           /*
3888             This works, but is only good for ints.
3889             It also requires a "known zero" register.
3890             emitpcode(POC_MOVLW, popGetLit(mlit & 0xff));
3891             emitpcode(POC_ADDFW, popGet(AOP(left),0));
3892             emitpcode(POC_RLFW,  popCopyReg(&pc_kzero));
3893             emitpcode(POC_ADDLW, popGetLit( ((mlit>>8) & 0xff)));
3894             emitpcode(POC_ADDFW, popGet(AOP(left),1));
3895             genSkipc(&rFalseIfx);
3896
3897             emitpLabel(truelbl->key);
3898             if(ifx) ifx->generated = 1;
3899             return;
3900           **/
3901           
3902           /* There are no more special cases, so perform a general compare */
3903   
3904           emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3905           emitpcode(POC_SUBFW, popGet(AOP(left),size));
3906
3907           while(size--) {
3908
3909             emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
3910             emitSKPNZ;
3911             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3912           }
3913           //rFalseIfx.condition ^= 1;
3914           genSkipc(&rFalseIfx);
3915
3916           emitpLabel(truelbl->key);
3917
3918           if(ifx) ifx->generated = 1;
3919           return;
3920
3921
3922         }
3923
3924
3925         /* sign is out of the way. So now do an unsigned compare */
3926         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
3927
3928
3929         //genChkZeroes(left)
3930
3931         /* General case - compare to an unsigned literal on the right.*/
3932
3933         i = (lit >> (size*8)) & 0xff;
3934         emitpcode(POC_MOVLW, popGetLit(i));
3935         emitpcode(POC_SUBFW, popGet(AOP(left),size));
3936         while(size--) {
3937           i = (lit >> (size*8)) & 0xff;
3938
3939           if(i) {
3940             emitpcode(POC_MOVLW, popGetLit(i));
3941             emitSKPNZ;
3942             emitpcode(POC_SUBFW, popGet(AOP(left),size));
3943           } else {
3944             /* this byte of the lit is zero, 
3945              *if it's not the last then OR in the variable */
3946             if(size)
3947               emitpcode(POC_IORFW, popGet(AOP(left),size));
3948           }
3949         }
3950
3951
3952         emitpLabel(lbl->key);
3953         //if(emitFinalCheck)
3954           genSkipc(&rFalseIfx);
3955         if(sign)
3956           emitpLabel(truelbl->key);
3957
3958         if(ifx) ifx->generated = 1;
3959         return;
3960
3961
3962       }
3963
3964       if(AOP_TYPE(left) == AOP_LIT) {
3965         //symbol *lbl = newiTempLabel(NULL);
3966
3967         lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
3968
3969
3970         DEBUGpic14_emitcode(";left lit","lit = %d,sign=%d",lit,sign);
3971
3972         /* Special cases */
3973         if((lit == 0) && (sign == 0)){
3974
3975           size--;
3976           emitpcode(POC_MOVFW, popGet(AOP(right),size));
3977           while(size) 
3978             emitpcode(POC_IORFW, popGet(AOP(right),--size));
3979
3980           //rFalseIfx.condition ^= 1;
3981           genSkipz2(&rFalseIfx);
3982           if(ifx) ifx->generated = 1;
3983           return;
3984         }
3985
3986         if(size==1) {
3987           /* Special cases */
3988           lit &= 0xff;
3989           if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
3990             /* degenerate compare can never be true */
3991             if(rFalseIfx.condition == 0)
3992               emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3993
3994             if(ifx) ifx->generated = 1;
3995             return;
3996           }
3997
3998           if(sign) {
3999             if((lit+1)&0xff) {
4000               emitpcode(POC_MOVFW, popGet(AOP(right),0));
4001               emitpcode(POC_ADDLW, popGetLit(0x80));
4002               emitpcode(POC_ADDLW, popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4003               rFalseIfx.condition ^= 1;
4004               genSkipc(&rFalseIfx);
4005             } else {
4006               rFalseIfx.condition ^= 1;
4007               genSkipCond(&rFalseIfx,right,0,7);
4008             }
4009             
4010           } else {
4011             if(lit & 0xff) {
4012               emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4013               emitpcode(POC_SUBFW, popGet(AOP(right),0));
4014               DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4015               rFalseIfx.condition ^= 1;
4016               genSkipc(&rFalseIfx);
4017             } else { 
4018               emitpcode(POC_MOVFW, popGet(AOP(right),0));
4019               genSkipz2(&rFalseIfx);
4020             }
4021           }
4022
4023           if(ifx) ifx->generated = 1;
4024           return;
4025
4026         } else {
4027
4028           /* Size is greater than 1 */
4029
4030
4031
4032           if(sign) {
4033             int lp1 = lit+1;
4034
4035             size--;
4036
4037             if(lp1 == 0) {
4038               /* this means lit = 0xffffffff, or -1 */
4039
4040
4041               DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4042               rFalseIfx.condition ^= 1;
4043               genSkipCond(&rFalseIfx,right,size,7);
4044               if(ifx) ifx->generated = 1;
4045               return;
4046             }
4047
4048             if(lit == 0) {
4049               int s = size;
4050
4051               if(rFalseIfx.condition) {
4052                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4053                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4054               }
4055
4056               emitpcode(POC_MOVFW, popGet(AOP(right),size));
4057               while(size--)
4058                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4059
4060
4061               emitSKPZ;
4062               if(rFalseIfx.condition) {
4063                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4064                 emitpLabel(truelbl->key);
4065               }else {
4066                 rFalseIfx.condition ^= 1;
4067                 genSkipCond(&rFalseIfx,right,s,7);
4068               }
4069
4070               if(ifx) ifx->generated = 1;
4071               return;
4072             }
4073
4074
4075             if(lit & (0x80 << (size*8))) {
4076               /* Lit is less than zero */
4077               DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4078               //rFalseIfx.condition ^= 1;
4079               //genSkipCond(&rFalseIfx,left,size,7);
4080               //rFalseIfx.condition ^= 1;
4081               emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4082               //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4083
4084               if(rFalseIfx.condition)
4085                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4086               else
4087                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4088
4089
4090             } else {
4091               /* Lit is greater than or equal to zero */
4092               DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4093               //rFalseIfx.condition ^= 1;
4094               //genSkipCond(&rFalseIfx,right,size,7);
4095               //rFalseIfx.condition ^= 1;
4096
4097               //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4098               //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4099
4100               emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4101               if(rFalseIfx.condition)
4102                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4103               else
4104                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4105
4106             }
4107             emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4108             emitpcode(POC_SUBFW, popGet(AOP(right),size));
4109
4110             while(size--) {
4111
4112               emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4113               emitSKPNZ;
4114               emitpcode(POC_SUBFW, popGet(AOP(right),size));
4115             }
4116             rFalseIfx.condition ^= 1;
4117             //rFalseIfx.condition = 1;
4118             genSkipc(&rFalseIfx);
4119
4120             emitpLabel(truelbl->key);
4121
4122             if(ifx) ifx->generated = 1;
4123             return;
4124
4125           } else {
4126             /* Unsigned compare for sizes greater than 1 */
4127
4128             while(size--) {
4129               i = (lit >> (size*8)) & 0xff;
4130
4131
4132               if(size) {
4133                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4134                 emitpcode(POC_MOVLW, popGetLit(i&0xff));
4135                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4136                 emitSKPZ;
4137                 emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4138               } else {
4139                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4140                 emitpcode(POC_MOVLW, popGetLit((i+1)&0xff));
4141                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4142
4143               }
4144             }
4145
4146             DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4147
4148             emitpLabel(lbl->key);
4149
4150             rFalseIfx.condition ^= 1;
4151             genSkipc(&rFalseIfx);
4152
4153           }
4154         if(sign)
4155           emitpLabel(truelbl->key);
4156         if(ifx) ifx->generated = 1;
4157         return;
4158         }
4159       }
4160       /* Compare two variables */
4161
4162       DEBUGpic14_emitcode(";sign","%d",sign);
4163
4164       size--;
4165       if(sign) {
4166         /* Sigh. thus sucks... */
4167         if(size) {
4168           emitpcode(POC_MOVFW, popGet(AOP(left),size));
4169           emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4170           emitpcode(POC_MOVLW, popGetLit(0x80));
4171           emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4172           emitpcode(POC_XORFW, popGet(AOP(right),size));
4173           emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4174         } else {
4175           /* Signed char comparison */
4176           /* Special thanks to Nikolai Golovchenko for this snippet */
4177           emitpcode(POC_MOVFW, popGet(AOP(right),0));
4178           emitpcode(POC_SUBFW, popGet(AOP(left),0));
4179           emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4180           emitpcode(POC_XORFW, popGet(AOP(left),0));
4181           emitpcode(POC_XORFW, popGet(AOP(right),0));
4182           emitpcode(POC_ADDLW, popGetLit(0x80));
4183
4184           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4185           genSkipc(&rFalseIfx);
4186           
4187           if(ifx) ifx->generated = 1;
4188           return;
4189         }
4190
4191       } else {
4192
4193         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4194         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4195       }
4196
4197
4198       /* The rest of the bytes of a multi-byte compare */
4199       while (size) {
4200
4201         emitSKPZ;
4202         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4203         size--;
4204
4205         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4206         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4207
4208
4209       }
4210
4211       emitpLabel(lbl->key);
4212
4213       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4214       genSkipc(&rFalseIfx);
4215       if(ifx) ifx->generated = 1;
4216       return;
4217
4218     }
4219   }
4220
4221   //release:
4222   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4223     pic14_outBitC(result);
4224   } else {
4225     /* if the result is used in the next
4226        ifx conditional branch then generate
4227        code a little differently */
4228     if (ifx )
4229       genIfxJump (ifx,"c");
4230     else
4231       pic14_outBitC(result);
4232     /* leave the result in acc */
4233   }
4234
4235 }
4236
4237 /*-----------------------------------------------------------------*/
4238 /* genCmpGt :- greater than comparison                             */
4239 /*-----------------------------------------------------------------*/
4240 static void genCmpGt (iCode *ic, iCode *ifx)
4241 {
4242     operand *left, *right, *result;
4243     sym_link *letype , *retype;
4244     int sign ;
4245
4246     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4247     left = IC_LEFT(ic);
4248     right= IC_RIGHT(ic);
4249     result = IC_RESULT(ic);
4250
4251     letype = getSpec(operandType(left));
4252     retype =getSpec(operandType(right));
4253     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4254     /* assign the amsops */
4255     aopOp (left,ic,FALSE);
4256     aopOp (right,ic,FALSE);
4257     aopOp (result,ic,TRUE);
4258
4259     genCmp(right, left, result, ifx, sign);
4260
4261     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4262     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4263     freeAsmop(result,NULL,ic,TRUE); 
4264 }
4265
4266 /*-----------------------------------------------------------------*/
4267 /* genCmpLt - less than comparisons                                */
4268 /*-----------------------------------------------------------------*/
4269 static void genCmpLt (iCode *ic, iCode *ifx)
4270 {
4271     operand *left, *right, *result;
4272     sym_link *letype , *retype;
4273     int sign ;
4274
4275     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4276     left = IC_LEFT(ic);
4277     right= IC_RIGHT(ic);
4278     result = IC_RESULT(ic);
4279
4280     letype = getSpec(operandType(left));
4281     retype =getSpec(operandType(right));
4282     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4283
4284     /* assign the amsops */
4285     aopOp (left,ic,FALSE);
4286     aopOp (right,ic,FALSE);
4287     aopOp (result,ic,TRUE);
4288
4289     genCmp(left, right, result, ifx, sign);
4290
4291     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4292     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4293     freeAsmop(result,NULL,ic,TRUE); 
4294 }
4295
4296 /*-----------------------------------------------------------------*/
4297 /* genc16bit2lit - compare a 16 bit value to a literal             */
4298 /*-----------------------------------------------------------------*/
4299 static void genc16bit2lit(operand *op, int lit, int offset)
4300 {
4301   int i;
4302
4303   DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4304   if( (lit&0xff) == 0) 
4305     i=1;
4306   else
4307     i=0;
4308
4309   switch( BYTEofLONG(lit,i)) { 
4310   case 0:
4311     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4312     break;
4313   case 1:
4314     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4315     break;
4316   case 0xff:
4317     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4318     break;
4319   default:
4320     emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4321     emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4322   }
4323
4324   i ^= 1;
4325
4326   switch( BYTEofLONG(lit,i)) { 
4327   case 0:
4328     emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4329     break;
4330   case 1:
4331     emitSKPNZ;
4332     emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4333     break;
4334   case 0xff:
4335     emitSKPNZ;
4336     emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4337     break;
4338   default:
4339     emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4340     emitSKPNZ;
4341     emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4342
4343   }
4344
4345 }
4346
4347 /*-----------------------------------------------------------------*/
4348 /* gencjneshort - compare and jump if not equal                    */
4349 /*-----------------------------------------------------------------*/
4350 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4351 {
4352   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4353   int offset = 0;
4354   resolvedIfx rIfx;
4355   symbol *lbl;
4356
4357   unsigned long lit = 0L;
4358   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4359   DEBUGpic14_AopType(__LINE__,left,right,NULL);
4360
4361   resolveIfx(&rIfx,ifx);
4362   lbl =  newiTempLabel(NULL);
4363
4364
4365   /* if the left side is a literal or 
4366      if the right is in a pointer register and left 
4367      is not */
4368   if ((AOP_TYPE(left) == AOP_LIT) || 
4369       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4370     operand *t = right;
4371     right = left;
4372     left = t;
4373   }
4374   if(AOP_TYPE(right) == AOP_LIT)
4375     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4376
4377   /* if the right side is a literal then anything goes */
4378   if (AOP_TYPE(right) == AOP_LIT &&
4379       AOP_TYPE(left) != AOP_DIR ) {
4380     switch(size) {
4381     case 2:
4382       genc16bit2lit(left, lit, 0);
4383       emitSKPNZ;
4384       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4385       break;
4386     default:
4387       while (size--) {
4388         if(lit & 0xff) {
4389           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4390           emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4391         } else {
4392           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4393         }
4394
4395         emitSKPNZ;
4396         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4397         offset++;
4398         lit >>= 8;
4399       }
4400       break;
4401     }
4402   }
4403
4404   /* if the right side is in a register or in direct space or
4405      if the left is a pointer register & right is not */    
4406   else if (AOP_TYPE(right) == AOP_REG ||
4407            AOP_TYPE(right) == AOP_DIR || 
4408            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4409            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4410     switch(size) {
4411     case 2:
4412       genc16bit2lit(left, lit, 0);
4413       emitSKPNZ;
4414       emitpcode(POC_GOTO,popGetLabel(lbl->key));
4415       break;
4416     default:
4417       while (size--) {
4418         int emit_skip=1;
4419         if((AOP_TYPE(left) == AOP_DIR) && 
4420            ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4421
4422           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4423           emitpcode(POC_XORFW,popGet(AOP(right),offset));
4424
4425         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4426             
4427           switch (lit & 0xff) {
4428           case 0:
4429             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4430             break;
4431           case 1:
4432             emitpcode(POC_DECFSZ,popGet(AOP(left),offset));
4433             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4434             emit_skip=0;
4435             break;
4436           case 0xff:
4437             emitpcode(POC_INCFSZ,popGet(AOP(left),offset));
4438             emitpcode(POC_GOTO,popGetLabel(lbl->key));
4439             emit_skip=0;
4440             break;
4441           default:
4442             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4443             emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4444           }
4445           lit >>= 8;
4446
4447         } else {
4448           emitpcode(POC_MOVF,popGet(AOP(left),offset));
4449         }
4450         if(emit_skip) {
4451           if(AOP_TYPE(result) == AOP_CRY) {
4452             pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4453             if(rIfx.condition)
4454               emitSKPNZ;
4455             else
4456               emitSKPZ;
4457             emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4458           } else {
4459             /* fix me. probably need to check result size too */
4460             emitpcode(POC_CLRF,popGet(AOP(result),0));
4461             if(rIfx.condition)
4462               emitSKPNZ;
4463             else
4464               emitSKPZ;
4465             emitpcode(POC_INCF,popGet(AOP(result),0));
4466           }
4467           if(ifx)
4468             ifx->generated=1;
4469         }
4470         emit_skip++;
4471         offset++;
4472       }
4473       break;
4474     }
4475   } else if(AOP_TYPE(right) == AOP_REG &&
4476             AOP_TYPE(left) != AOP_DIR){
4477
4478     while(size--) {
4479       emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4480       emitpcode(POC_XORFW,popGet(AOP(right),offset));
4481       pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4482       if(rIfx.condition)
4483         emitSKPNZ;
4484       else
4485         emitSKPZ;
4486       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4487       offset++;
4488     }
4489       
4490   }else{
4491     /* right is a pointer reg need both a & b */
4492     while(size--) {
4493       char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4494       if(strcmp(l,"b"))
4495         pic14_emitcode("mov","b,%s",l);
4496       MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4497       pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4498       offset++;
4499     }
4500   }
4501   emitpLabel(lbl->key);
4502
4503   if(ifx)
4504     ifx->generated = 1;
4505 }
4506
4507 #if 0
4508 /*-----------------------------------------------------------------*/
4509 /* gencjne - compare and jump if not equal                         */
4510 /*-----------------------------------------------------------------*/
4511 static void gencjne(operand *left, operand *right, iCode *ifx)
4512 {
4513     symbol *tlbl  = newiTempLabel(NULL);
4514
4515     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4516     gencjneshort(left, right, lbl);
4517
4518     pic14_emitcode("mov","a,%s",one);
4519     pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4520     pic14_emitcode("","%05d_DS_:",lbl->key+100);
4521     pic14_emitcode("clr","a");
4522     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4523
4524     emitpLabel(lbl->key);
4525     emitpLabel(tlbl->key);
4526
4527 }
4528 #endif
4529
4530 /*-----------------------------------------------------------------*/
4531 /* genCmpEq - generates code for equal to                          */
4532 /*-----------------------------------------------------------------*/
4533 static void genCmpEq (iCode *ic, iCode *ifx)
4534 {
4535     operand *left, *right, *result;
4536     unsigned long lit = 0L;
4537     int size,offset=0;
4538
4539     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4540
4541     if(ifx)
4542       DEBUGpic14_emitcode ("; ifx is non-null","");
4543     else
4544       DEBUGpic14_emitcode ("; ifx is null","");
4545
4546     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4547     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4548     aopOp((result=IC_RESULT(ic)),ic,TRUE);
4549
4550     size = max(AOP_SIZE(left),AOP_SIZE(right));
4551
4552     DEBUGpic14_AopType(__LINE__,left,right,result);
4553
4554     /* if literal, literal on the right or 
4555     if the right is in a pointer register and left 
4556     is not */
4557     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4558         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4559       operand *tmp = right ;
4560       right = left;
4561       left = tmp;
4562     }
4563
4564
4565     if(ifx && !AOP_SIZE(result)){
4566         symbol *tlbl;
4567         /* if they are both bit variables */
4568         if (AOP_TYPE(left) == AOP_CRY &&
4569             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4570             if(AOP_TYPE(right) == AOP_LIT){
4571                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4572                 if(lit == 0L){
4573                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4574                     pic14_emitcode("cpl","c");
4575                 } else if(lit == 1L) {
4576                     pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4577                 } else {
4578                     pic14_emitcode("clr","c");
4579                 }
4580                 /* AOP_TYPE(right) == AOP_CRY */
4581             } else {
4582                 symbol *lbl = newiTempLabel(NULL);
4583                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4584                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4585                 pic14_emitcode("cpl","c");
4586                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4587             }
4588             /* if true label then we jump if condition
4589             supplied is true */
4590             tlbl = newiTempLabel(NULL);
4591             if ( IC_TRUE(ifx) ) {
4592                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4593                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4594             } else {
4595                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4596                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4597             }
4598             pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4599
4600             {
4601               /* left and right are both bit variables, result is carry */
4602               resolvedIfx rIfx;
4603               
4604               resolveIfx(&rIfx,ifx);
4605
4606               emitpcode(POC_MOVLW,popGet(AOP(left),0));
4607               emitpcode(POC_ANDFW,popGet(AOP(left),0));
4608               emitpcode(POC_BTFSC,popGet(AOP(right),0));
4609               emitpcode(POC_ANDLW,popGet(AOP(left),0));
4610               genSkipz2(&rIfx);
4611             }
4612         } else {
4613
4614           /* They're not both bit variables. Is the right a literal? */
4615           if(AOP_TYPE(right) == AOP_LIT) {
4616             lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4617             
4618             switch(size) {
4619
4620             case 1:
4621               switch(lit & 0xff) {
4622               case 1:
4623                 if ( IC_TRUE(ifx) ) {
4624                   emitpcode(POC_DECFW,popGet(AOP(left),offset));
4625                   emitSKPNZ;
4626                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4627                 } else {
4628                   emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4629                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4630                 }
4631                 break;
4632               case 0xff:
4633                 if ( IC_TRUE(ifx) ) {
4634                   emitpcode(POC_INCFW,popGet(AOP(left),offset));
4635                   emitSKPNZ;
4636                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4637                 } else {
4638                   emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4639                   emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4640                 }
4641                 break;
4642               default:
4643                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4644                 if(lit)
4645                   emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4646                 genSkip(ifx,'z');
4647               }
4648
4649
4650               /* end of size == 1 */
4651               break;
4652               
4653             case 2:
4654               genc16bit2lit(left,lit,offset);
4655               genSkip(ifx,'z');
4656               break;
4657               /* end of size == 2 */
4658
4659             default:
4660               /* size is 4 */
4661               if(lit==0) {
4662                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
4663                 emitpcode(POC_IORFW,popGet(AOP(left),1));
4664                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4665                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4666
4667               } else {
4668
4669                 /* search for patterns that can be optimized */
4670
4671                 genc16bit2lit(left,lit,0);
4672                 lit >>= 16;
4673                 if(lit) {
4674                   genSkipz(ifx,IC_TRUE(ifx) == NULL);
4675                   //genSkip(ifx,'z');
4676                   genc16bit2lit(left,lit,2);
4677                 } else {
4678                   emitpcode(POC_IORFW,popGet(AOP(left),2));
4679                   emitpcode(POC_IORFW,popGet(AOP(left),3));
4680
4681                 }
4682                 
4683               }
4684
4685               genSkip(ifx,'z');
4686             }
4687           
4688             ifx->generated = 1;
4689             goto release ;
4690             
4691
4692           } else if(AOP_TYPE(right) == AOP_CRY ) {
4693             /* we know the left is not a bit, but that the right is */
4694             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4695             emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4696                       popGet(AOP(right),offset));
4697             emitpcode(POC_XORLW,popGetLit(1));
4698
4699             /* if the two are equal, then W will be 0 and the Z bit is set
4700              * we could test Z now, or go ahead and check the high order bytes if
4701              * the variable we're comparing is larger than a byte. */
4702
4703             while(--size)
4704               emitpcode(POC_IORFW,popGet(AOP(left),offset));
4705
4706             if ( IC_TRUE(ifx) ) {
4707               emitSKPNZ;
4708               emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4709               pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4710             } else {
4711               emitSKPZ;
4712               emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4713               pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4714             }
4715
4716           } else {
4717             /* They're both variables that are larger than bits */
4718             int s = size;
4719
4720             tlbl = newiTempLabel(NULL);
4721
4722             while(size--) {
4723               emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4724               emitpcode(POC_XORFW,popGet(AOP(right),offset));
4725
4726               if ( IC_TRUE(ifx) ) {
4727                 if(size) {
4728                   emitSKPZ;
4729                   emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4730                   pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4731                 } else {
4732                   emitSKPNZ;
4733                   emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4734                   pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4735                 }
4736               } else {
4737                 emitSKPZ;
4738                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4739                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4740               }
4741               offset++;
4742             }
4743             if(s>1 && IC_TRUE(ifx)) {
4744               emitpLabel(tlbl->key);
4745               pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
4746             }
4747           }
4748         }
4749         /* mark the icode as generated */
4750         ifx->generated = 1;
4751         goto release ;
4752     }
4753
4754     /* if they are both bit variables */
4755     if (AOP_TYPE(left) == AOP_CRY &&
4756         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4757         if(AOP_TYPE(right) == AOP_LIT){
4758             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4759             if(lit == 0L){
4760                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4761                 pic14_emitcode("cpl","c");
4762             } else if(lit == 1L) {
4763                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4764             } else {
4765                 pic14_emitcode("clr","c");
4766             }
4767             /* AOP_TYPE(right) == AOP_CRY */
4768         } else {
4769             symbol *lbl = newiTempLabel(NULL);
4770             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4771             pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4772             pic14_emitcode("cpl","c");
4773             pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4774         }
4775         /* c = 1 if egal */
4776         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
4777             pic14_outBitC(result);
4778             goto release ;
4779         }
4780         if (ifx) {
4781             genIfxJump (ifx,"c");
4782             goto release ;
4783         }
4784         /* if the result is used in an arithmetic operation
4785         then put the result in place */
4786         pic14_outBitC(result);
4787     } else {
4788       
4789       gencjne(left,right,result,ifx);
4790 /*
4791       if(ifx) 
4792         gencjne(left,right,newiTempLabel(NULL));
4793       else {
4794         if(IC_TRUE(ifx)->key)
4795           gencjne(left,right,IC_TRUE(ifx)->key);
4796         else
4797           gencjne(left,right,IC_FALSE(ifx)->key);
4798         ifx->generated = 1;
4799         goto release ;
4800       }
4801       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4802         aopPut(AOP(result),"a",0);
4803         goto release ;
4804       }
4805
4806       if (ifx) {
4807         genIfxJump (ifx,"a");
4808         goto release ;
4809       }
4810 */
4811       /* if the result is used in an arithmetic operation
4812          then put the result in place */
4813 /*
4814       if (AOP_TYPE(result) != AOP_CRY) 
4815         pic14_outAcc(result);
4816 */
4817       /* leave the result in acc */
4818     }
4819
4820 release:
4821     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4822     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4823     freeAsmop(result,NULL,ic,TRUE);
4824 }
4825
4826 /*-----------------------------------------------------------------*/
4827 /* ifxForOp - returns the icode containing the ifx for operand     */
4828 /*-----------------------------------------------------------------*/
4829 static iCode *ifxForOp ( operand *op, iCode *ic )
4830 {
4831     /* if true symbol then needs to be assigned */
4832     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4833     if (IS_TRUE_SYMOP(op))
4834         return NULL ;
4835
4836     /* if this has register type condition and
4837     the next instruction is ifx with the same operand
4838     and live to of the operand is upto the ifx only then */
4839     if (ic->next &&
4840         ic->next->op == IFX &&
4841         IC_COND(ic->next)->key == op->key &&
4842         OP_SYMBOL(op)->liveTo <= ic->next->seq )
4843         return ic->next;
4844
4845     if (ic->next &&
4846         ic->next->op == IFX &&
4847         IC_COND(ic->next)->key == op->key) {
4848       DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
4849       return ic->next;
4850     }
4851
4852     DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
4853     if (ic->next &&
4854         ic->next->op == IFX)
4855       DEBUGpic14_emitcode ("; ic-next"," is an IFX");
4856
4857     if (ic->next &&
4858         ic->next->op == IFX &&
4859         IC_COND(ic->next)->key == op->key) {
4860       DEBUGpic14_emitcode ("; "," key is okay");
4861       DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
4862                            OP_SYMBOL(op)->liveTo,
4863                            ic->next->seq);
4864     }
4865
4866
4867     return NULL;
4868 }
4869 /*-----------------------------------------------------------------*/
4870 /* genAndOp - for && operation                                     */
4871 /*-----------------------------------------------------------------*/
4872 static void genAndOp (iCode *ic)
4873 {
4874     operand *left,*right, *result;
4875     symbol *tlbl;
4876
4877     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4878     /* note here that && operations that are in an
4879     if statement are taken away by backPatchLabels
4880     only those used in arthmetic operations remain */
4881     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4882     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4883     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4884
4885     /* if both are bit variables */
4886     if (AOP_TYPE(left) == AOP_CRY &&
4887         AOP_TYPE(right) == AOP_CRY ) {
4888         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4889         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir);
4890         pic14_outBitC(result);
4891     } else {
4892         tlbl = newiTempLabel(NULL);
4893         pic14_toBoolean(left);    
4894         pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
4895         pic14_toBoolean(right);
4896         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4897         pic14_outBitAcc(result);
4898     }
4899
4900     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4901     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4902     freeAsmop(result,NULL,ic,TRUE);
4903 }
4904
4905
4906 /*-----------------------------------------------------------------*/
4907 /* genOrOp - for || operation                                      */
4908 /*-----------------------------------------------------------------*/
4909 /*
4910   tsd pic port -
4911   modified this code, but it doesn't appear to ever get called
4912 */
4913
4914 static void genOrOp (iCode *ic)
4915 {
4916     operand *left,*right, *result;
4917     symbol *tlbl;
4918
4919     /* note here that || operations that are in an
4920     if statement are taken away by backPatchLabels
4921     only those used in arthmetic operations remain */
4922     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4923     aopOp((left=IC_LEFT(ic)),ic,FALSE);
4924     aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4925     aopOp((result=IC_RESULT(ic)),ic,FALSE);
4926
4927     DEBUGpic14_AopType(__LINE__,left,right,result);
4928
4929     /* if both are bit variables */
4930     if (AOP_TYPE(left) == AOP_CRY &&
4931         AOP_TYPE(right) == AOP_CRY ) {
4932       pic14_emitcode("clrc","");
4933       pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
4934                AOP(left)->aopu.aop_dir,
4935                AOP(left)->aopu.aop_dir);
4936       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
4937                AOP(right)->aopu.aop_dir,
4938                AOP(right)->aopu.aop_dir);
4939       pic14_emitcode("setc","");
4940
4941     } else {
4942         tlbl = newiTempLabel(NULL);
4943         pic14_toBoolean(left);
4944         emitSKPZ;
4945         pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
4946         pic14_toBoolean(right);
4947         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4948
4949         pic14_outBitAcc(result);
4950     }
4951
4952     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4953     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4954     freeAsmop(result,NULL,ic,TRUE);            
4955 }
4956
4957 /*-----------------------------------------------------------------*/
4958 /* isLiteralBit - test if lit == 2^n                               */
4959 /*-----------------------------------------------------------------*/
4960 static int isLiteralBit(unsigned long lit)
4961 {
4962     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
4963     0x100L,0x200L,0x400L,0x800L,
4964     0x1000L,0x2000L,0x4000L,0x8000L,
4965     0x10000L,0x20000L,0x40000L,0x80000L,
4966     0x100000L,0x200000L,0x400000L,0x800000L,
4967     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
4968     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
4969     int idx;
4970     
4971     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4972     for(idx = 0; idx < 32; idx++)
4973         if(lit == pw[idx])
4974             return idx+1;
4975     return 0;
4976 }
4977
4978 /*-----------------------------------------------------------------*/
4979 /* continueIfTrue -                                                */
4980 /*-----------------------------------------------------------------*/
4981 static void continueIfTrue (iCode *ic)
4982 {
4983     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4984     if(IC_TRUE(ic))
4985         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
4986     ic->generated = 1;
4987 }
4988
4989 /*-----------------------------------------------------------------*/
4990 /* jmpIfTrue -                                                     */
4991 /*-----------------------------------------------------------------*/
4992 static void jumpIfTrue (iCode *ic)
4993 {
4994     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4995     if(!IC_TRUE(ic))
4996         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
4997     ic->generated = 1;
4998 }
4999
5000 /*-----------------------------------------------------------------*/
5001 /* jmpTrueOrFalse -                                                */
5002 /*-----------------------------------------------------------------*/
5003 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5004 {
5005     // ugly but optimized by peephole
5006     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5007     if(IC_TRUE(ic)){
5008         symbol *nlbl = newiTempLabel(NULL);
5009         pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5010         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5011         pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5012         pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5013     }
5014     else{
5015         pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5016         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5017     }
5018     ic->generated = 1;
5019 }
5020
5021 /*-----------------------------------------------------------------*/
5022 /* genAnd  - code for and                                          */
5023 /*-----------------------------------------------------------------*/
5024 static void genAnd (iCode *ic, iCode *ifx)
5025 {
5026   operand *left, *right, *result;
5027   int size, offset=0;  
5028   unsigned long lit = 0L;
5029   int bytelit = 0;
5030   resolvedIfx rIfx;
5031
5032
5033   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5034   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5035   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5036   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5037
5038   resolveIfx(&rIfx,ifx);
5039
5040   /* if left is a literal & right is not then exchange them */
5041   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5042       AOP_NEEDSACC(left)) {
5043     operand *tmp = right ;
5044     right = left;
5045     left = tmp;
5046   }
5047
5048   /* if result = right then exchange them */
5049   if(pic14_sameRegs(AOP(result),AOP(right))){
5050     operand *tmp = right ;
5051     right = left;
5052     left = tmp;
5053   }
5054
5055   /* if right is bit then exchange them */
5056   if (AOP_TYPE(right) == AOP_CRY &&
5057       AOP_TYPE(left) != AOP_CRY){
5058     operand *tmp = right ;
5059     right = left;
5060     left = tmp;
5061   }
5062   if(AOP_TYPE(right) == AOP_LIT)
5063     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5064
5065   size = AOP_SIZE(result);
5066
5067   DEBUGpic14_AopType(__LINE__,left,right,result);
5068
5069   // if(bit & yy)
5070   // result = bit & yy;
5071   if (AOP_TYPE(left) == AOP_CRY){
5072     // c = bit & literal;
5073     if(AOP_TYPE(right) == AOP_LIT){
5074       if(lit & 1) {
5075         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5076           // no change
5077           goto release;
5078         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5079       } else {
5080         // bit(result) = 0;
5081         if(size && (AOP_TYPE(result) == AOP_CRY)){
5082           pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5083           goto release;
5084         }
5085         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5086           jumpIfTrue(ifx);
5087           goto release;
5088         }
5089         pic14_emitcode("clr","c");
5090       }
5091     } else {
5092       if (AOP_TYPE(right) == AOP_CRY){
5093         // c = bit & bit;
5094         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5095         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5096       } else {
5097         // c = bit & val;
5098         MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5099         // c = lsb
5100         pic14_emitcode("rrc","a");
5101         pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5102       }
5103     }
5104     // bit = c
5105     // val = c
5106     if(size)
5107       pic14_outBitC(result);
5108     // if(bit & ...)
5109     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5110       genIfxJump(ifx, "c");           
5111     goto release ;
5112   }
5113
5114   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5115   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5116   if((AOP_TYPE(right) == AOP_LIT) &&
5117      (AOP_TYPE(result) == AOP_CRY) &&
5118      (AOP_TYPE(left) != AOP_CRY)){
5119     int posbit = isLiteralBit(lit);
5120     /* left &  2^n */
5121     if(posbit){
5122       posbit--;
5123       //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5124       // bit = left & 2^n
5125       if(size)
5126         pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5127       // if(left &  2^n)
5128       else{
5129         if(ifx){
5130 /*
5131           if(IC_TRUE(ifx)) {
5132             emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5133             emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
5134           } else {
5135             emitpcode(POC_BTFSS,newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5136             emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
5137           }
5138 */
5139           emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5140                     newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5141           emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5142           
5143           ifx->generated = 1;
5144         }
5145         goto release;
5146       }
5147     } else {
5148       symbol *tlbl = newiTempLabel(NULL);
5149       int sizel = AOP_SIZE(left);
5150       if(size)
5151         pic14_emitcode("setb","c");
5152       while(sizel--){
5153         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5154           MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5155           // byte ==  2^n ?
5156           if((posbit = isLiteralBit(bytelit)) != 0)
5157             pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5158           else{
5159             if(bytelit != 0x0FFL)
5160               pic14_emitcode("anl","a,%s",
5161                              aopGet(AOP(right),offset,FALSE,TRUE));
5162             pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5163           }
5164         }
5165         offset++;
5166       }
5167       // bit = left & literal
5168       if(size){
5169         pic14_emitcode("clr","c");
5170         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5171       }
5172       // if(left & literal)
5173       else{
5174         if(ifx)
5175           jmpTrueOrFalse(ifx, tlbl);
5176         goto release ;
5177       }
5178     }
5179     pic14_outBitC(result);
5180     goto release ;
5181   }
5182
5183   /* if left is same as result */
5184   if(pic14_sameRegs(AOP(result),AOP(left))){
5185     int know_W = -1;
5186     for(;size--; offset++,lit>>=8) {
5187       if(AOP_TYPE(right) == AOP_LIT){
5188         switch(lit & 0xff) {
5189         case 0x00:
5190           /*  and'ing with 0 has clears the result */
5191           pic14_emitcode("clrf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5192           emitpcode(POC_CLRF,popGet(AOP(result),offset));
5193           break;
5194         case 0xff:
5195           /* and'ing with 0xff is a nop when the result and left are the same */
5196           break;
5197
5198         default:
5199           {
5200             int p = my_powof2( (~lit) & 0xff );
5201             if(p>=0) {
5202               /* only one bit is set in the literal, so use a bcf instruction */
5203               pic14_emitcode("bcf","%s,%d",aopGet(AOP(left),offset,FALSE,TRUE),p);
5204               emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5205
5206             } else {
5207               pic14_emitcode("movlw","0x%x", (lit & 0xff));
5208               pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE));
5209               if(know_W != (lit&0xff))
5210                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5211               know_W = lit &0xff;
5212               emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5213             }
5214           }    
5215         }
5216       } else {
5217         if (AOP_TYPE(left) == AOP_ACC) {
5218           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5219         } else {                    
5220           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5221           emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5222
5223         }
5224       }
5225     }
5226
5227   } else {
5228     // left & result in different registers
5229     if(AOP_TYPE(result) == AOP_CRY){
5230       // result = bit
5231       // if(size), result in bit
5232       // if(!size && ifx), conditional oper: if(left & right)
5233       symbol *tlbl = newiTempLabel(NULL);
5234       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5235       if(size)
5236         pic14_emitcode("setb","c");
5237       while(sizer--){
5238         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5239         pic14_emitcode("anl","a,%s",
5240                        aopGet(AOP(left),offset,FALSE,FALSE));
5241         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5242         offset++;
5243       }
5244       if(size){
5245         CLRC;
5246         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5247         pic14_outBitC(result);
5248       } else if(ifx)
5249         jmpTrueOrFalse(ifx, tlbl);
5250     } else {
5251       for(;(size--);offset++) {
5252         // normal case
5253         // result = left & right
5254         if(AOP_TYPE(right) == AOP_LIT){
5255           int t = (lit >> (offset*8)) & 0x0FFL;
5256           switch(t) { 
5257           case 0x00:
5258             pic14_emitcode("clrf","%s",
5259                            aopGet(AOP(result),offset,FALSE,FALSE));
5260             emitpcode(POC_CLRF,popGet(AOP(result),offset));
5261             break;
5262           case 0xff:
5263             pic14_emitcode("movf","%s,w",
5264                            aopGet(AOP(left),offset,FALSE,FALSE));
5265             pic14_emitcode("movwf","%s",
5266                            aopGet(AOP(result),offset,FALSE,FALSE));
5267             emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5268             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5269             break;
5270           default:
5271             pic14_emitcode("movlw","0x%x",t);
5272             pic14_emitcode("andwf","%s,w",
5273                            aopGet(AOP(left),offset,FALSE,FALSE));
5274             pic14_emitcode("movwf","%s",
5275                            aopGet(AOP(result),offset,FALSE,FALSE));
5276               
5277             emitpcode(POC_MOVLW, popGetLit(t));
5278             emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5279             emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5280           }
5281           continue;
5282         }
5283
5284         if (AOP_TYPE(left) == AOP_ACC) {
5285           pic14_emitcode("andwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5286           emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5287         } else {
5288           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5289           pic14_emitcode("andwf","%s,w",
5290                          aopGet(AOP(left),offset,FALSE,FALSE));
5291           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5292           emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5293         }
5294         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5295         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5296       }
5297     }
5298   }
5299
5300   release :
5301     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5302   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5303   freeAsmop(result,NULL,ic,TRUE);     
5304 }
5305
5306 /*-----------------------------------------------------------------*/
5307 /* genOr  - code for or                                            */
5308 /*-----------------------------------------------------------------*/
5309 static void genOr (iCode *ic, iCode *ifx)
5310 {
5311     operand *left, *right, *result;
5312     int size, offset=0;
5313     unsigned long lit = 0L;
5314
5315     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5316
5317     aopOp((left = IC_LEFT(ic)),ic,FALSE);
5318     aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5319     aopOp((result=IC_RESULT(ic)),ic,TRUE);
5320
5321     DEBUGpic14_AopType(__LINE__,left,right,result);
5322
5323     /* if left is a literal & right is not then exchange them */
5324     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5325         AOP_NEEDSACC(left)) {
5326         operand *tmp = right ;
5327         right = left;
5328         left = tmp;
5329     }
5330
5331     /* if result = right then exchange them */
5332     if(pic14_sameRegs(AOP(result),AOP(right))){
5333         operand *tmp = right ;
5334         right = left;
5335         left = tmp;
5336     }
5337
5338     /* if right is bit then exchange them */
5339     if (AOP_TYPE(right) == AOP_CRY &&
5340         AOP_TYPE(left) != AOP_CRY){
5341         operand *tmp = right ;
5342         right = left;
5343         left = tmp;
5344     }
5345
5346     DEBUGpic14_AopType(__LINE__,left,right,result);
5347
5348     if(AOP_TYPE(right) == AOP_LIT)
5349         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5350
5351     size = AOP_SIZE(result);
5352
5353     // if(bit | yy)
5354     // xx = bit | yy;
5355     if (AOP_TYPE(left) == AOP_CRY){
5356         if(AOP_TYPE(right) == AOP_LIT){
5357             // c = bit & literal;
5358             if(lit){
5359                 // lit != 0 => result = 1
5360                 if(AOP_TYPE(result) == AOP_CRY){
5361                   if(size)
5362                     emitpcode(POC_BSF, popGet(AOP(result),0));
5363                   //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5364                   //     AOP(result)->aopu.aop_dir,
5365                   //     AOP(result)->aopu.aop_dir);
5366                     else if(ifx)
5367                         continueIfTrue(ifx);
5368                     goto release;
5369                 }
5370             } else {
5371                 // lit == 0 => result = left
5372                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5373                     goto release;
5374                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5375             }
5376         } else {
5377             if (AOP_TYPE(right) == AOP_CRY){
5378               if(pic14_sameRegs(AOP(result),AOP(left))){
5379                 // c = bit | bit;
5380                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5381                 emitpcode(POC_BTFSC, popGet(AOP(right),0));
5382                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5383
5384                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5385                          AOP(result)->aopu.aop_dir,
5386                          AOP(result)->aopu.aop_dir);
5387                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5388                          AOP(right)->aopu.aop_dir,
5389                          AOP(right)->aopu.aop_dir);
5390                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5391                          AOP(result)->aopu.aop_dir,
5392                          AOP(result)->aopu.aop_dir);
5393               } else {
5394                 if( AOP_TYPE(result) == AOP_ACC) {
5395                   emitpcode(POC_MOVLW, popGetLit(0));
5396                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5397                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5398                   emitpcode(POC_MOVLW, popGetLit(1));
5399
5400                 } else {
5401
5402                   emitpcode(POC_BCF,   popGet(AOP(result),0));
5403                   emitpcode(POC_BTFSS, popGet(AOP(right),0));
5404                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5405                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5406
5407                   pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5408                                  AOP(result)->aopu.aop_dir,
5409                                  AOP(result)->aopu.aop_dir);
5410                   pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5411                                  AOP(right)->aopu.aop_dir,
5412                                  AOP(right)->aopu.aop_dir);
5413                   pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5414                                  AOP(left)->aopu.aop_dir,
5415                                  AOP(left)->aopu.aop_dir);
5416                   pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5417                                  AOP(result)->aopu.aop_dir,
5418                                  AOP(result)->aopu.aop_dir);
5419                 }
5420               }
5421             } else {
5422                 // c = bit | val;
5423                 symbol *tlbl = newiTempLabel(NULL);
5424                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5425
5426
5427                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5428                 if( AOP_TYPE(right) == AOP_ACC) {
5429                   emitpcode(POC_IORLW, popGetLit(0));
5430                   emitSKPNZ;
5431                   emitpcode(POC_BTFSC, popGet(AOP(left),0));
5432                   emitpcode(POC_BSF,   popGet(AOP(result),0));
5433                 }
5434
5435
5436
5437                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5438                     pic14_emitcode(";XXX setb","c");
5439                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5440                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5441                 pic14_toBoolean(right);
5442                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5443                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5444                     jmpTrueOrFalse(ifx, tlbl);
5445                     goto release;
5446                 } else {
5447                     CLRC;
5448                     pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5449                 }
5450             }
5451         }
5452         // bit = c
5453         // val = c
5454         if(size)
5455             pic14_outBitC(result);
5456         // if(bit | ...)
5457         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5458             genIfxJump(ifx, "c");           
5459         goto release ;
5460     }
5461
5462     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5463     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5464     if((AOP_TYPE(right) == AOP_LIT) &&
5465        (AOP_TYPE(result) == AOP_CRY) &&
5466        (AOP_TYPE(left) != AOP_CRY)){
5467         if(lit){
5468           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5469             // result = 1
5470             if(size)
5471                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5472             else 
5473                 continueIfTrue(ifx);
5474             goto release;
5475         } else {
5476           pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5477             // lit = 0, result = boolean(left)
5478             if(size)
5479                 pic14_emitcode(";XXX setb","c");
5480             pic14_toBoolean(right);
5481             if(size){
5482                 symbol *tlbl = newiTempLabel(NULL);
5483                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5484                 CLRC;
5485                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5486             } else {
5487                 genIfxJump (ifx,"a");
5488                 goto release;
5489             }
5490         }
5491         pic14_outBitC(result);
5492         goto release ;
5493     }
5494
5495     /* if left is same as result */
5496     if(pic14_sameRegs(AOP(result),AOP(left))){
5497       int know_W = -1;
5498       for(;size--; offset++,lit>>=8) {
5499         if(AOP_TYPE(right) == AOP_LIT){
5500           if((lit & 0xff) == 0)
5501             /*  or'ing with 0 has no effect */
5502             continue;
5503           else {
5504             int p = my_powof2(lit & 0xff);
5505             if(p>=0) {
5506               /* only one bit is set in the literal, so use a bsf instruction */
5507               emitpcode(POC_BSF,
5508                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5509             } else {
5510               if(know_W != (lit & 0xff))
5511                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5512               know_W = lit & 0xff;
5513               emitpcode(POC_IORWF, popGet(AOP(left),offset));
5514             }
5515                     
5516           }
5517         } else {
5518           if (AOP_TYPE(left) == AOP_ACC) {
5519             emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5520             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5521           } else {                  
5522             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5523             emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5524
5525             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5526             pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5527
5528           }
5529         }
5530       }
5531     } else {
5532         // left & result in different registers
5533         if(AOP_TYPE(result) == AOP_CRY){
5534             // result = bit
5535             // if(size), result in bit
5536             // if(!size && ifx), conditional oper: if(left | right)
5537             symbol *tlbl = newiTempLabel(NULL);
5538             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5539             pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5540
5541
5542             if(size)
5543                 pic14_emitcode(";XXX setb","c");
5544             while(sizer--){
5545                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5546                 pic14_emitcode(";XXX orl","a,%s",
5547                          aopGet(AOP(left),offset,FALSE,FALSE));
5548                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5549                 offset++;
5550             }
5551             if(size){
5552                 CLRC;
5553                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5554                 pic14_outBitC(result);
5555             } else if(ifx)
5556                 jmpTrueOrFalse(ifx, tlbl);
5557         } else for(;(size--);offset++){
5558           // normal case
5559           // result = left & right
5560           if(AOP_TYPE(right) == AOP_LIT){
5561             int t = (lit >> (offset*8)) & 0x0FFL;
5562             switch(t) { 
5563             case 0x00:
5564               emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5565               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5566
5567               pic14_emitcode("movf","%s,w",
5568                        aopGet(AOP(left),offset,FALSE,FALSE));
5569               pic14_emitcode("movwf","%s",
5570                        aopGet(AOP(result),offset,FALSE,FALSE));
5571               break;
5572             default:
5573               emitpcode(POC_MOVLW,  popGetLit(t));
5574               emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5575               emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5576
5577               pic14_emitcode("movlw","0x%x",t);
5578               pic14_emitcode("iorwf","%s,w",
5579                        aopGet(AOP(left),offset,FALSE,FALSE));
5580               pic14_emitcode("movwf","%s",
5581                        aopGet(AOP(result),offset,FALSE,FALSE));
5582               
5583             }
5584             continue;
5585           }
5586
5587           // faster than result <- left, anl result,right
5588           // and better if result is SFR
5589           if (AOP_TYPE(left) == AOP_ACC) {
5590             emitpcode(POC_IORWF,  popGet(AOP(right),offset));
5591             pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5592           } else {
5593             emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5594             emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5595
5596             pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5597             pic14_emitcode("iorwf","%s,w",
5598                      aopGet(AOP(left),offset,FALSE,FALSE));
5599           }
5600           emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5601           pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5602         }
5603     }
5604
5605 release :
5606     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5607     freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5608     freeAsmop(result,NULL,ic,TRUE);     
5609 }
5610
5611 /*-----------------------------------------------------------------*/
5612 /* genXor - code for xclusive or                                   */
5613 /*-----------------------------------------------------------------*/
5614 static void genXor (iCode *ic, iCode *ifx)
5615 {
5616   operand *left, *right, *result;
5617   int size, offset=0;
5618   unsigned long lit = 0L;
5619
5620   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5621
5622   aopOp((left = IC_LEFT(ic)),ic,FALSE);
5623   aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5624   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5625
5626   /* if left is a literal & right is not ||
5627      if left needs acc & right does not */
5628   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5629       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5630     operand *tmp = right ;
5631     right = left;
5632     left = tmp;
5633   }
5634
5635   /* if result = right then exchange them */
5636   if(pic14_sameRegs(AOP(result),AOP(right))){
5637     operand *tmp = right ;
5638     right = left;
5639     left = tmp;
5640   }
5641
5642   /* if right is bit then exchange them */
5643   if (AOP_TYPE(right) == AOP_CRY &&
5644       AOP_TYPE(left) != AOP_CRY){
5645     operand *tmp = right ;
5646     right = left;
5647     left = tmp;
5648   }
5649   if(AOP_TYPE(right) == AOP_LIT)
5650     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5651
5652   size = AOP_SIZE(result);
5653
5654   // if(bit ^ yy)
5655   // xx = bit ^ yy;
5656   if (AOP_TYPE(left) == AOP_CRY){
5657     if(AOP_TYPE(right) == AOP_LIT){
5658       // c = bit & literal;
5659       if(lit>>1){
5660         // lit>>1  != 0 => result = 1
5661         if(AOP_TYPE(result) == AOP_CRY){
5662           if(size)
5663             {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5664             pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5665           else if(ifx)
5666             continueIfTrue(ifx);
5667           goto release;
5668         }
5669         pic14_emitcode("setb","c");
5670       } else{
5671         // lit == (0 or 1)
5672         if(lit == 0){
5673           // lit == 0, result = left
5674           if(size && pic14_sameRegs(AOP(result),AOP(left)))
5675             goto release;
5676           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5677         } else{
5678           // lit == 1, result = not(left)
5679           if(size && pic14_sameRegs(AOP(result),AOP(left))){
5680             emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5681             emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5682             pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5683             goto release;
5684           } else {
5685             pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5686             pic14_emitcode("cpl","c");
5687           }
5688         }
5689       }
5690
5691     } else {
5692       // right != literal
5693       symbol *tlbl = newiTempLabel(NULL);
5694       if (AOP_TYPE(right) == AOP_CRY){
5695         // c = bit ^ bit;
5696         pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5697       }
5698       else{
5699         int sizer = AOP_SIZE(right);
5700         // c = bit ^ val
5701         // if val>>1 != 0, result = 1
5702         pic14_emitcode("setb","c");
5703         while(sizer){
5704           MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5705           if(sizer == 1)
5706             // test the msb of the lsb
5707             pic14_emitcode("anl","a,#0xfe");
5708           pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5709           sizer--;
5710         }
5711         // val = (0,1)
5712         pic14_emitcode("rrc","a");
5713       }
5714       pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5715       pic14_emitcode("cpl","c");
5716       pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5717     }
5718     // bit = c
5719     // val = c
5720     if(size)
5721       pic14_outBitC(result);
5722     // if(bit | ...)
5723     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5724       genIfxJump(ifx, "c");           
5725     goto release ;
5726   }
5727
5728   if(pic14_sameRegs(AOP(result),AOP(left))){
5729     /* if left is same as result */
5730     for(;size--; offset++) {
5731       if(AOP_TYPE(right) == AOP_LIT){
5732         int t  = (lit >> (offset*8)) & 0x0FFL;
5733         if(t == 0x00L)
5734           continue;
5735         else
5736           if (IS_AOP_PREG(left)) {
5737             MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5738             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5739             aopPut(AOP(result),"a",offset);
5740           } else {
5741             emitpcode(POC_MOVLW, popGetLit(t));
5742             emitpcode(POC_XORWF,popGet(AOP(left),offset));
5743             pic14_emitcode("xrl","%s,%s",
5744                            aopGet(AOP(left),offset,FALSE,TRUE),
5745                            aopGet(AOP(right),offset,FALSE,FALSE));
5746           }
5747       } else {
5748         if (AOP_TYPE(left) == AOP_ACC)
5749           pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
5750         else {
5751           emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5752           emitpcode(POC_XORWF,popGet(AOP(left),offset));
5753 /*
5754           if (IS_AOP_PREG(left)) {
5755             pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5756             aopPut(AOP(result),"a",offset);
5757           } else
5758             pic14_emitcode("xrl","%s,a",
5759                            aopGet(AOP(left),offset,FALSE,TRUE));
5760 */
5761         }
5762       }
5763     }
5764   } else {
5765     // left & result in different registers
5766     if(AOP_TYPE(result) == AOP_CRY){
5767       // result = bit
5768       // if(size), result in bit
5769       // if(!size && ifx), conditional oper: if(left ^ right)
5770       symbol *tlbl = newiTempLabel(NULL);
5771       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5772       if(size)
5773         pic14_emitcode("setb","c");
5774       while(sizer--){
5775         if((AOP_TYPE(right) == AOP_LIT) &&
5776            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
5777           MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
5778         } else {
5779           MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5780           pic14_emitcode("xrl","a,%s",
5781                          aopGet(AOP(left),offset,FALSE,FALSE));
5782         }
5783         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5784         offset++;
5785       }
5786       if(size){
5787         CLRC;
5788         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5789         pic14_outBitC(result);
5790       } else if(ifx)
5791         jmpTrueOrFalse(ifx, tlbl);
5792     } else for(;(size--);offset++){
5793       // normal case
5794       // result = left & right
5795       if(AOP_TYPE(right) == AOP_LIT){
5796         int t = (lit >> (offset*8)) & 0x0FFL;
5797         switch(t) { 
5798         case 0x00:
5799           emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5800           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5801           pic14_emitcode("movf","%s,w",
5802                          aopGet(AOP(left),offset,FALSE,FALSE));
5803           pic14_emitcode("movwf","%s",
5804                          aopGet(AOP(result),offset,FALSE,FALSE));
5805           break;
5806         case 0xff:
5807           emitpcode(POC_COMFW,popGet(AOP(left),offset));
5808           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5809           pic14_emitcode("comf","%s,w",
5810                          aopGet(AOP(left),offset,FALSE,FALSE));
5811           pic14_emitcode("movwf","%s",
5812                          aopGet(AOP(result),offset,FALSE,FALSE));
5813           break;
5814         default:
5815           emitpcode(POC_MOVLW, popGetLit(t));
5816           emitpcode(POC_XORFW,popGet(AOP(left),offset));
5817           emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5818           pic14_emitcode("movlw","0x%x",t);
5819           pic14_emitcode("xorwf","%s,w",
5820                          aopGet(AOP(left),offset,FALSE,FALSE));
5821           pic14_emitcode("movwf","%s",
5822                          aopGet(AOP(result),offset,FALSE,FALSE));
5823
5824         }
5825         continue;
5826       }
5827
5828       // faster than result <- left, anl result,right
5829       // and better if result is SFR
5830       if (AOP_TYPE(left) == AOP_ACC) {
5831         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5832         pic14_emitcode("xorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5833       } else {
5834         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5835         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5836         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5837         pic14_emitcode("xorwf","%s,w",aopGet(AOP(left),offset,FALSE,FALSE));
5838       }
5839       if ( AOP_TYPE(result) != AOP_ACC){
5840         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5841         pic14_emitcode("movwf","%s",aopGet(AOP(result),offset,FALSE,FALSE));
5842       }
5843     }
5844   }
5845
5846   release :
5847     freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5848   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5849   freeAsmop(result,NULL,ic,TRUE);     
5850 }
5851
5852 /*-----------------------------------------------------------------*/
5853 /* genInline - write the inline code out                           */
5854 /*-----------------------------------------------------------------*/
5855 static void genInline (iCode *ic)
5856 {
5857     char *buffer, *bp, *bp1;
5858     
5859     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5860
5861     _G.inLine += (!options.asmpeep);
5862
5863     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5864     strcpy(buffer,IC_INLINE(ic));
5865
5866     /* emit each line as a code */
5867     while (*bp) {
5868         if (*bp == '\n') {
5869             *bp++ = '\0';
5870             pic14_emitcode(bp1,"");
5871             addpCode2pBlock(pb,newpCodeInlineP(bp1));
5872             bp1 = bp;
5873         } else {
5874             if (*bp == ':') {
5875                 bp++;
5876                 *bp = '\0';
5877                 bp++;
5878                 pic14_emitcode(bp1,"");
5879                 bp1 = bp;
5880             } else
5881                 bp++;
5882         }
5883     }
5884     if (bp1 != bp) {
5885         pic14_emitcode(bp1,"");
5886         addpCode2pBlock(pb,newpCodeInlineP(bp1));
5887     }
5888     /*     pic14_emitcode("",buffer); */
5889     _G.inLine -= (!options.asmpeep);
5890 }
5891
5892 /*-----------------------------------------------------------------*/
5893 /* genRRC - rotate right with carry                                */
5894 /*-----------------------------------------------------------------*/
5895 static void genRRC (iCode *ic)
5896 {
5897   operand *left , *result ;
5898   int size, offset = 0, same;
5899
5900   /* rotate right with carry */
5901   left = IC_LEFT(ic);
5902   result=IC_RESULT(ic);
5903   aopOp (left,ic,FALSE);
5904   aopOp (result,ic,FALSE);
5905
5906   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5907
5908   same = pic14_sameRegs(AOP(result),AOP(left));
5909
5910   size = AOP_SIZE(result);    
5911
5912   /* get the lsb and put it into the carry */
5913   emitpcode(POC_RRFW, popGet(AOP(left),size-1));
5914
5915   offset = 0 ;
5916
5917   while(size--) {
5918
5919     if(same) {
5920       emitpcode(POC_RRF, popGet(AOP(left),offset));
5921     } else {
5922       emitpcode(POC_RRFW, popGet(AOP(left),offset));
5923       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5924     }
5925
5926     offset++;
5927   }
5928
5929   freeAsmop(left,NULL,ic,TRUE);
5930   freeAsmop(result,NULL,ic,TRUE);
5931 }
5932
5933 /*-----------------------------------------------------------------*/
5934 /* genRLC - generate code for rotate left with carry               */
5935 /*-----------------------------------------------------------------*/
5936 static void genRLC (iCode *ic)
5937 {    
5938   operand *left , *result ;
5939   int size, offset = 0;
5940   int same;
5941
5942   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5943   /* rotate right with carry */
5944   left = IC_LEFT(ic);
5945   result=IC_RESULT(ic);
5946   aopOp (left,ic,FALSE);
5947   aopOp (result,ic,FALSE);
5948
5949   DEBUGpic14_AopType(__LINE__,left,NULL,result);
5950
5951   same = pic14_sameRegs(AOP(result),AOP(left));
5952
5953   /* move it to the result */
5954   size = AOP_SIZE(result);    
5955
5956   /* get the msb and put it into the carry */
5957   emitpcode(POC_RLFW, popGet(AOP(left),size-1));
5958
5959   offset = 0 ;
5960
5961   while(size--) {
5962
5963     if(same) {
5964       emitpcode(POC_RLF, popGet(AOP(left),offset));
5965     } else {
5966       emitpcode(POC_RLFW, popGet(AOP(left),offset));
5967       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
5968     }
5969
5970     offset++;
5971   }
5972
5973
5974   freeAsmop(left,NULL,ic,TRUE);
5975   freeAsmop(result,NULL,ic,TRUE);
5976 }
5977
5978 /*-----------------------------------------------------------------*/
5979 /* genGetHbit - generates code get highest order bit               */
5980 /*-----------------------------------------------------------------*/
5981 static void genGetHbit (iCode *ic)
5982 {
5983     operand *left, *result;
5984     left = IC_LEFT(ic);
5985     result=IC_RESULT(ic);
5986     aopOp (left,ic,FALSE);
5987     aopOp (result,ic,FALSE);
5988
5989     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5990     /* get the highest order byte into a */
5991     MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
5992     if(AOP_TYPE(result) == AOP_CRY){
5993         pic14_emitcode("rlc","a");
5994         pic14_outBitC(result);
5995     }
5996     else{
5997         pic14_emitcode("rl","a");
5998         pic14_emitcode("anl","a,#0x01");
5999         pic14_outAcc(result);
6000     }
6001
6002
6003     freeAsmop(left,NULL,ic,TRUE);
6004     freeAsmop(result,NULL,ic,TRUE);
6005 }
6006
6007 /*-----------------------------------------------------------------*/
6008 /* AccRol - rotate left accumulator by known count                 */
6009 /*-----------------------------------------------------------------*/
6010 static void AccRol (int shCount)
6011 {
6012     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6013     shCount &= 0x0007;              // shCount : 0..7
6014     switch(shCount){
6015         case 0 :
6016             break;
6017         case 1 :
6018             pic14_emitcode("rl","a");
6019             break;
6020         case 2 :
6021             pic14_emitcode("rl","a");
6022             pic14_emitcode("rl","a");
6023             break;
6024         case 3 :
6025             pic14_emitcode("swap","a");
6026             pic14_emitcode("rr","a");
6027             break;
6028         case 4 :
6029             pic14_emitcode("swap","a");
6030             break;
6031         case 5 :
6032             pic14_emitcode("swap","a");
6033             pic14_emitcode("rl","a");
6034             break;
6035         case 6 :
6036             pic14_emitcode("rr","a");
6037             pic14_emitcode("rr","a");
6038             break;
6039         case 7 :
6040             pic14_emitcode("rr","a");
6041             break;
6042     }
6043 }
6044
6045 /*-----------------------------------------------------------------*/
6046 /* AccLsh - left shift accumulator by known count                  */
6047 /*-----------------------------------------------------------------*/
6048 static void AccLsh (int shCount)
6049 {
6050     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6051     if(shCount != 0){
6052         if(shCount == 1)
6053             pic14_emitcode("add","a,acc");
6054         else 
6055             if(shCount == 2) {
6056             pic14_emitcode("add","a,acc");
6057             pic14_emitcode("add","a,acc");
6058         } else {
6059             /* rotate left accumulator */
6060             AccRol(shCount);
6061             /* and kill the lower order bits */
6062             pic14_emitcode("anl","a,#0x%02x", SLMask[shCount]);
6063         }
6064     }
6065 }
6066
6067 /*-----------------------------------------------------------------*/
6068 /* AccRsh - right shift accumulator by known count                 */
6069 /*-----------------------------------------------------------------*/
6070 static void AccRsh (int shCount)
6071 {
6072     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6073     if(shCount != 0){
6074         if(shCount == 1){
6075             CLRC;
6076             pic14_emitcode("rrc","a");
6077         } else {
6078             /* rotate right accumulator */
6079             AccRol(8 - shCount);
6080             /* and kill the higher order bits */
6081             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6082         }
6083     }
6084 }
6085
6086 #if 0
6087 /*-----------------------------------------------------------------*/
6088 /* AccSRsh - signed right shift accumulator by known count                 */
6089 /*-----------------------------------------------------------------*/
6090 static void AccSRsh (int shCount)
6091 {
6092     symbol *tlbl ;
6093     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6094     if(shCount != 0){
6095         if(shCount == 1){
6096             pic14_emitcode("mov","c,acc.7");
6097             pic14_emitcode("rrc","a");
6098         } else if(shCount == 2){
6099             pic14_emitcode("mov","c,acc.7");
6100             pic14_emitcode("rrc","a");
6101             pic14_emitcode("mov","c,acc.7");
6102             pic14_emitcode("rrc","a");
6103         } else {
6104             tlbl = newiTempLabel(NULL);
6105             /* rotate right accumulator */
6106             AccRol(8 - shCount);
6107             /* and kill the higher order bits */
6108             pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6109             pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6110             pic14_emitcode("orl","a,#0x%02x",
6111                      (unsigned char)~SRMask[shCount]);
6112             pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6113         }
6114     }
6115 }
6116 #endif
6117 /*-----------------------------------------------------------------*/
6118 /* shiftR1Left2Result - shift right one byte from left to result   */
6119 /*-----------------------------------------------------------------*/
6120 static void shiftR1Left2ResultSigned (operand *left, int offl,
6121                                 operand *result, int offr,
6122                                 int shCount)
6123 {
6124   int same;
6125
6126   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6127
6128   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6129
6130   switch(shCount) {
6131   case 1:
6132     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6133     if(same) 
6134       emitpcode(POC_RRF, popGet(AOP(result),offr));
6135     else {
6136       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6137       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6138     }
6139
6140     break;
6141   case 2:
6142
6143     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6144     if(same) 
6145       emitpcode(POC_RRF, popGet(AOP(result),offr));
6146     else {
6147       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6148       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6149     }
6150     emitpcode(POC_RLFW, popGet(AOP(result),offl));
6151     emitpcode(POC_RRF,  popGet(AOP(result),offl));
6152
6153     break;
6154
6155   case 3:
6156     if(same)
6157       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6158     else {
6159       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6160       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6161     }
6162
6163     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6164     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6165     emitpcode(POC_ANDLW, popGetLit(0x1f));
6166
6167     emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6168     emitpcode(POC_IORLW, popGetLit(0xe0));
6169
6170     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6171     break;
6172
6173   case 4:
6174     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6175     emitpcode(POC_ANDLW,  popGetLit(0x0f));
6176     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6177     emitpcode(POC_IORLW,  popGetLit(0xf0));
6178     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6179     break;
6180   case 5:
6181     if(same) {
6182       emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6183     } else {
6184       emitpcode(POC_SWAPFW,  popGet(AOP(result),offr));
6185       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6186     }
6187     emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6188     emitpcode(POC_ANDLW,  popGetLit(0x07));
6189     emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6190     emitpcode(POC_IORLW,  popGetLit(0xf8));
6191     emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6192
6193
6194
6195     break;
6196
6197   case 6:
6198     if(same) {
6199       emitpcode(POC_MOVLW, popGetLit(0x00));
6200       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6201       emitpcode(POC_MOVLW, popGetLit(0xfe));
6202       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),6,0));
6203       emitpcode(POC_IORLW, popGetLit(0x01));
6204       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6205     } else {
6206       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6207       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6208       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6209       emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6210       emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6211     }
6212     break;
6213
6214   case 7:
6215     if(same) {
6216       emitpcode(POC_MOVLW, popGetLit(0x00));
6217       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6218       emitpcode(POC_MOVLW, popGetLit(0xff));
6219       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6220     } else {
6221       emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6222       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6223       emitpcode(POC_DECF,  popGet(AOP(result),offr));
6224     }
6225
6226   default:
6227     break;
6228   }
6229 }
6230
6231 /*-----------------------------------------------------------------*/
6232 /* shiftR1Left2Result - shift right one byte from left to result   */
6233 /*-----------------------------------------------------------------*/
6234 static void shiftR1Left2Result (operand *left, int offl,
6235                                 operand *result, int offr,
6236                                 int shCount, int sign)
6237 {
6238   int same;
6239
6240   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6241
6242   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6243
6244   /* Copy the msb into the carry if signed. */
6245   if(sign) {
6246     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6247     return;
6248   }
6249
6250
6251
6252   switch(shCount) {
6253   case 1:
6254     emitCLRC;
6255     if(same) 
6256       emitpcode(POC_RRF, popGet(AOP(result),offr));
6257     else {
6258       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6259       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6260     }
6261     break;
6262   case 2:
6263     emitCLRC;
6264     if(same) {
6265       emitpcode(POC_RRF, popGet(AOP(result),offr));
6266     } else {
6267       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6268       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6269     }
6270     emitCLRC;
6271     emitpcode(POC_RRF, popGet(AOP(result),offr));
6272
6273     break;
6274   case 3:
6275     if(same)
6276       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6277     else {
6278       emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6279       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6280     }
6281
6282     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6283     emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6284     emitpcode(POC_ANDLW, popGetLit(0x1f));
6285     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6286     break;
6287       
6288   case 4:
6289     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6290     emitpcode(POC_ANDLW, popGetLit(0x0f));
6291     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6292     break;
6293
6294   case 5:
6295     emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6296     emitpcode(POC_ANDLW, popGetLit(0x0f));
6297     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6298     emitCLRC;
6299     emitpcode(POC_RRF, popGet(AOP(result),offr));
6300
6301     break;
6302   case 6:
6303
6304     emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6305     emitpcode(POC_ANDLW, popGetLit(0x80));
6306     emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6307     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6308     emitpcode(POC_RLF,   popGet(AOP(result),offr));
6309     break;
6310
6311   case 7:
6312
6313     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6314     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6315     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6316
6317     break;
6318
6319   default:
6320     break;
6321   }
6322 }
6323
6324 /*-----------------------------------------------------------------*/
6325 /* shiftL1Left2Result - shift left one byte from left to result    */
6326 /*-----------------------------------------------------------------*/
6327 static void shiftL1Left2Result (operand *left, int offl,
6328                                 operand *result, int offr, int shCount)
6329 {
6330   int same;
6331
6332   //    char *l;
6333   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6334
6335   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6336   DEBUGpic14_emitcode ("; ***","same =  %d",same);
6337     //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6338     //    MOVA(l);
6339     /* shift left accumulator */
6340     //AccLsh(shCount); // don't comment out just yet...
6341   //    aopPut(AOP(result),"a",offr);
6342
6343   switch(shCount) {
6344   case 1:
6345     /* Shift left 1 bit position */
6346     emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6347     if(same) {
6348       emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6349     } else {
6350       emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6351       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6352     }
6353     break;
6354   case 2:
6355     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6356     emitpcode(POC_ANDLW,popGetLit(0x7e));
6357     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6358     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6359     break;
6360   case 3:
6361     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6362     emitpcode(POC_ANDLW,popGetLit(0x3e));
6363     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6364     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6365     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6366     break;
6367   case 4:
6368     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6369     emitpcode(POC_ANDLW, popGetLit(0xf0));
6370     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6371     break;
6372   case 5:
6373     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6374     emitpcode(POC_ANDLW, popGetLit(0xf0));
6375     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6376     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6377     break;
6378   case 6:
6379     emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6380     emitpcode(POC_ANDLW, popGetLit(0x30));
6381     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6382     emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6383     emitpcode(POC_RLF,  popGet(AOP(result),offr));
6384     break;
6385   case 7:
6386     emitpcode(POC_RRFW, popGet(AOP(left),offl));
6387     emitpcode(POC_CLRF, popGet(AOP(result),offr));
6388     emitpcode(POC_RRF,  popGet(AOP(result),offr));
6389     break;
6390
6391   default:
6392     DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6393   }
6394
6395 }
6396
6397 /*-----------------------------------------------------------------*/
6398 /* movLeft2Result - move byte from left to result                  */
6399 /*-----------------------------------------------------------------*/
6400 static void movLeft2Result (operand *left, int offl,
6401                             operand *result, int offr, int sign)
6402 {
6403   char *l;
6404   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6405   if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6406     l = aopGet(AOP(left),offl,FALSE,FALSE);
6407
6408     if (*l == '@' && (IS_AOP_PREG(result))) {
6409       pic14_emitcode("mov","a,%s",l);
6410       aopPut(AOP(result),"a",offr);
6411     } else {
6412       //if(!sign) {
6413       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6414       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6415
6416       //aopPut(AOP(result),l,offr);
6417       //}else{
6418       /* MSB sign in acc.7 ! */
6419       //if(pic14_getDataSize(left) == offl+1){
6420       //  pic14_emitcode("mov","a,%s",l);
6421       //  aopPut(AOP(result),"a",offr);
6422       //}
6423       //}
6424     }
6425   }
6426 }
6427
6428 /*-----------------------------------------------------------------*/
6429 /* shiftL2Left2Result - shift left two bytes from left to result   */
6430 /*-----------------------------------------------------------------*/
6431 static void shiftL2Left2Result (operand *left, int offl,
6432                                 operand *result, int offr, int shCount)
6433 {
6434
6435
6436   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6437
6438   if(pic14_sameRegs(AOP(result), AOP(left))) {
6439     switch(shCount) {
6440     case 0:
6441       break;
6442     case 1:
6443     case 2:
6444     case 3:
6445
6446       emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6447       emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6448       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6449
6450       while(--shCount) {
6451         emitCLRC;
6452         emitpcode(POC_RLF, popGet(AOP(result),offr));
6453         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6454       }
6455
6456       break;
6457     case 4:
6458     case 5:
6459       emitpcode(POC_MOVLW, popGetLit(0x0f));
6460       emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6461       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6462       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6463       emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6464       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6465       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6466       if(shCount >=5) {
6467         emitpcode(POC_RLF, popGet(AOP(result),offr));
6468         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6469       }
6470       break;
6471     case 6:
6472       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6473       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6474       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6475       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6476       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6477       emitpcode(POC_ANDLW,popGetLit(0xc0));
6478       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6479       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6480       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6481       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6482       break;
6483     case 7:
6484       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6485       emitpcode(POC_RRFW, popGet(AOP(result),offr));
6486       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6487       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6488       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6489     }
6490
6491   } else {
6492     switch(shCount) {
6493     case 0:
6494       break;
6495     case 1:
6496     case 2:
6497     case 3:
6498       /* note, use a mov/add for the shift since the mov has a
6499          chance of getting optimized out */
6500       emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6501       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6502       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6503       emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6504       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6505
6506       while(--shCount) {
6507         emitCLRC;
6508         emitpcode(POC_RLF, popGet(AOP(result),offr));
6509         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6510       }
6511       break;
6512
6513     case 4:
6514     case 5:
6515       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6516       emitpcode(POC_ANDLW, popGetLit(0xF0));
6517       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6518       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6519       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6520       emitpcode(POC_ANDLW, popGetLit(0xF0));
6521       emitpcode(POC_XORWF, popGet(AOP(result),offr));
6522       emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6523
6524
6525       if(shCount == 5) {
6526         emitpcode(POC_RLF, popGet(AOP(result),offr));
6527         emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6528       }
6529       break;
6530     case 6:
6531       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6532       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6533       emitpcode(POC_RRFW, popGet(AOP(result),offl));
6534       emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6535
6536       emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6537       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6538       emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6539       emitpcode(POC_ANDLW,popGetLit(0xc0));
6540       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6541       emitpcode(POC_XORWF,popGet(AOP(result),offr));
6542       emitpcode(POC_XORFW,popGet(AOP(result),offr));
6543       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6544       break;
6545     case 7:
6546       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6547       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6548       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6549       emitpcode(POC_CLRF, popGet(AOP(result),offr));
6550       emitpcode(POC_RRF,  popGet(AOP(result),offr));
6551     }
6552   }
6553
6554 }
6555 /*-----------------------------------------------------------------*/
6556 /* shiftR2Left2Result - shift right two bytes from left to result  */
6557 /*-----------------------------------------------------------------*/
6558 static void shiftR2Left2Result (operand *left, int offl,
6559                                 operand *result, int offr,
6560                                 int shCount, int sign)
6561 {
6562   int same=0;
6563
6564   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6565   same = pic14_sameRegs(AOP(result), AOP(left));
6566
6567   if(same && ((offl + MSB16) == offr)){
6568     same=1;
6569     /* don't crash result[offr] */
6570     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6571     pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6572   } else {
6573     movLeft2Result(left,offl, result, offr, 0);
6574     MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
6575   }
6576   /* a:x >> shCount (x = lsb(result))*/
6577 /*
6578   if(sign)
6579     AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6580   else {
6581     AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
6582 */
6583   switch(shCount) {
6584   case 0:
6585     break;
6586   case 1:
6587   case 2:
6588   case 3:
6589     emitCLRC;
6590     if(same) {
6591       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6592       emitpcode(POC_RRF,popGet(AOP(result),offr));
6593     } else {
6594
6595       emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6596       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6597       emitpcode(POC_RRFW, popGet(AOP(left),offl));
6598       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6599     }
6600
6601     while(--shCount) {
6602       emitCLRC;
6603       emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
6604       emitpcode(POC_RRF,popGet(AOP(result),offr));
6605     }
6606     break;
6607   case 4:
6608   case 5:
6609     if(same) {
6610
6611       emitpcode(POC_MOVLW, popGetLit(0xf0));
6612       emitpcode(POC_ANDWF, popGet(AOP(result),offr));
6613       emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6614
6615       emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6616       emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
6617       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6618       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6619     } else {
6620       emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6621       emitpcode(POC_ANDLW, popGetLit(0x0f));
6622       emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6623
6624       emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6625       emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6626       emitpcode(POC_ANDLW, popGetLit(0xf0));
6627       emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
6628       emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6629     }
6630
6631     if(shCount >=5) {
6632       emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
6633       emitpcode(POC_RRF, popGet(AOP(result),offr));
6634     }
6635
6636     break;
6637
6638   case 6:
6639     if(same) {
6640
6641       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6642       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6643
6644       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6645       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6646       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6647       emitpcode(POC_ANDLW,popGetLit(0x03));
6648       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6649       emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
6650       emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
6651       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6652     } else {
6653       emitpcode(POC_RLFW, popGet(AOP(left),offl));
6654       emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6655       emitpcode(POC_RLFW, popGet(AOP(result),offl+MSB16));
6656       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6657       emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6658       emitpcode(POC_RLF,  popGet(AOP(result),offr));
6659       emitpcode(POC_RLFW, popGet(AOP(result),offr));
6660       emitpcode(POC_ANDLW,popGetLit(0x03));
6661       emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6662     }
6663
6664     break;
6665   case 7:
6666     emitpcode(POC_RLFW, popGet(AOP(left),offl));
6667     emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
6668     emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6669     emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
6670     emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6671   }
6672 }
6673
6674
6675 /*-----------------------------------------------------------------*/
6676 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
6677 /*-----------------------------------------------------------------*/
6678 static void shiftLLeftOrResult (operand *left, int offl,
6679                                 operand *result, int offr, int shCount)
6680 {
6681     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6682     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6683     /* shift left accumulator */
6684     AccLsh(shCount);
6685     /* or with result */
6686     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6687     /* back to result */
6688     aopPut(AOP(result),"a",offr);
6689 }
6690
6691 /*-----------------------------------------------------------------*/
6692 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
6693 /*-----------------------------------------------------------------*/
6694 static void shiftRLeftOrResult (operand *left, int offl,
6695                                 operand *result, int offr, int shCount)
6696 {
6697     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6698     MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
6699     /* shift right accumulator */
6700     AccRsh(shCount);
6701     /* or with result */
6702     pic14_emitcode("orl","a,%s", aopGet(AOP(result),offr,FALSE,FALSE));
6703     /* back to result */
6704     aopPut(AOP(result),"a",offr);
6705 }
6706
6707 /*-----------------------------------------------------------------*/
6708 /* genlshOne - left shift a one byte quantity by known count       */
6709 /*-----------------------------------------------------------------*/
6710 static void genlshOne (operand *result, operand *left, int shCount)
6711 {       
6712     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6713     shiftL1Left2Result(left, LSB, result, LSB, shCount);
6714 }
6715
6716 /*-----------------------------------------------------------------*/
6717 /* genlshTwo - left shift two bytes by known amount != 0           */
6718 /*-----------------------------------------------------------------*/
6719 static void genlshTwo (operand *result,operand *left, int shCount)
6720 {
6721     int size;
6722     
6723     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6724     size = pic14_getDataSize(result);
6725
6726     /* if shCount >= 8 */
6727     if (shCount >= 8) {
6728         shCount -= 8 ;
6729
6730         if (size > 1){
6731             if (shCount)
6732                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6733             else 
6734                 movLeft2Result(left, LSB, result, MSB16, 0);
6735         }
6736         emitpcode(POC_CLRF,popGet(AOP(result),LSB));
6737     }
6738
6739     /*  1 <= shCount <= 7 */
6740     else {  
6741         if(size == 1)
6742             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
6743         else 
6744             shiftL2Left2Result(left, LSB, result, LSB, shCount);
6745     }
6746 }
6747
6748 /*-----------------------------------------------------------------*/
6749 /* shiftLLong - shift left one long from left to result            */
6750 /* offl = LSB or MSB16                                             */
6751 /*-----------------------------------------------------------------*/
6752 static void shiftLLong (operand *left, operand *result, int offr )
6753 {
6754     char *l;
6755     int size = AOP_SIZE(result);
6756
6757     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6758     if(size >= LSB+offr){
6759         l = aopGet(AOP(left),LSB,FALSE,FALSE);
6760         MOVA(l);
6761         pic14_emitcode("add","a,acc");
6762         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6763             size >= MSB16+offr && offr != LSB )
6764             pic14_emitcode("xch","a,%s",
6765                      aopGet(AOP(left),LSB+offr,FALSE,FALSE));
6766         else        
6767             aopPut(AOP(result),"a",LSB+offr);
6768     }
6769
6770     if(size >= MSB16+offr){
6771         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
6772             l = aopGet(AOP(left),MSB16,FALSE,FALSE);
6773             MOVA(l);
6774         }
6775         pic14_emitcode("rlc","a");
6776         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6777             size >= MSB24+offr && offr != LSB)
6778             pic14_emitcode("xch","a,%s",
6779                      aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
6780         else        
6781             aopPut(AOP(result),"a",MSB16+offr);
6782     }
6783
6784     if(size >= MSB24+offr){
6785         if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
6786             l = aopGet(AOP(left),MSB24,FALSE,FALSE);
6787             MOVA(l);
6788         }
6789         pic14_emitcode("rlc","a");
6790         if (pic14_sameRegs(AOP(left),AOP(result)) && 
6791             size >= MSB32+offr && offr != LSB )
6792             pic14_emitcode("xch","a,%s",
6793                      aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
6794         else        
6795             aopPut(AOP(result),"a",MSB24+offr);
6796     }
6797
6798     if(size > MSB32+offr){
6799         if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
6800             l = aopGet(AOP(left),MSB32,FALSE,FALSE);
6801             MOVA(l);    
6802         }
6803         pic14_emitcode("rlc","a");
6804         aopPut(AOP(result),"a",MSB32+offr);
6805     }
6806     if(offr != LSB)
6807         aopPut(AOP(result),zero,LSB);       
6808 }
6809
6810 /*-----------------------------------------------------------------*/
6811 /* genlshFour - shift four byte by a known amount != 0             */
6812 /*-----------------------------------------------------------------*/
6813 static void genlshFour (operand *result, operand *left, int shCount)
6814 {
6815     int size;
6816
6817     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6818     size = AOP_SIZE(result);
6819
6820     /* if shifting more that 3 bytes */
6821     if (shCount >= 24 ) {
6822         shCount -= 24;
6823         if (shCount)
6824             /* lowest order of left goes to the highest
6825             order of the destination */
6826             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
6827         else
6828             movLeft2Result(left, LSB, result, MSB32, 0);
6829         aopPut(AOP(result),zero,LSB);
6830         aopPut(AOP(result),zero,MSB16);
6831         aopPut(AOP(result),zero,MSB32);
6832         return;
6833     }
6834
6835     /* more than two bytes */
6836     else if ( shCount >= 16 ) {
6837         /* lower order two bytes goes to higher order two bytes */
6838         shCount -= 16;
6839         /* if some more remaining */
6840         if (shCount)
6841             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
6842         else {
6843             movLeft2Result(left, MSB16, result, MSB32, 0);
6844             movLeft2Result(left, LSB, result, MSB24, 0);
6845         }
6846         aopPut(AOP(result),zero,MSB16);
6847         aopPut(AOP(result),zero,LSB);
6848         return;
6849     }    
6850
6851     /* if more than 1 byte */
6852     else if ( shCount >= 8 ) {
6853         /* lower order three bytes goes to higher order  three bytes */
6854         shCount -= 8;
6855         if(size == 2){
6856             if(shCount)
6857                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6858             else
6859                 movLeft2Result(left, LSB, result, MSB16, 0);
6860         }
6861         else{   /* size = 4 */
6862             if(shCount == 0){
6863                 movLeft2Result(left, MSB24, result, MSB32, 0);
6864                 movLeft2Result(left, MSB16, result, MSB24, 0);
6865                 movLeft2Result(left, LSB, result, MSB16, 0);
6866                 aopPut(AOP(result),zero,LSB);
6867             }
6868             else if(shCount == 1)
6869                 shiftLLong(left, result, MSB16);
6870             else{
6871                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
6872                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
6873                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
6874                 aopPut(AOP(result),zero,LSB);
6875             }
6876         }
6877     }
6878
6879     /* 1 <= shCount <= 7 */
6880     else if(shCount <= 2){
6881         shiftLLong(left, result, LSB);
6882         if(shCount == 2)
6883             shiftLLong(result, result, LSB);
6884     }
6885     /* 3 <= shCount <= 7, optimize */
6886     else{
6887         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
6888         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
6889         shiftL2Left2Result(left, LSB, result, LSB, shCount);
6890     }
6891 }
6892
6893 /*-----------------------------------------------------------------*/
6894 /* genLeftShiftLiteral - left shifting by known count              */
6895 /*-----------------------------------------------------------------*/
6896 static void genLeftShiftLiteral (operand *left,
6897                                  operand *right,
6898                                  operand *result,
6899                                  iCode *ic)
6900 {    
6901     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
6902     int size;
6903
6904     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6905     freeAsmop(right,NULL,ic,TRUE);
6906
6907     aopOp(left,ic,FALSE);
6908     aopOp(result,ic,FALSE);
6909
6910     size = getSize(operandType(result));
6911
6912 #if VIEW_SIZE
6913     pic14_emitcode("; shift left ","result %d, left %d",size,
6914              AOP_SIZE(left));
6915 #endif
6916
6917     /* I suppose that the left size >= result size */
6918     if(shCount == 0){
6919         while(size--){
6920             movLeft2Result(left, size, result, size, 0);
6921         }
6922     }
6923
6924     else if(shCount >= (size * 8))
6925         while(size--)
6926             aopPut(AOP(result),zero,size);
6927     else{
6928         switch (size) {
6929             case 1:
6930                 genlshOne (result,left,shCount);
6931                 break;
6932
6933             case 2:
6934             case 3:
6935                 genlshTwo (result,left,shCount);
6936                 break;
6937
6938             case 4:
6939                 genlshFour (result,left,shCount);
6940                 break;
6941         }
6942     }
6943     freeAsmop(left,NULL,ic,TRUE);
6944     freeAsmop(result,NULL,ic,TRUE);
6945 }
6946
6947 /*-----------------------------------------------------------------*
6948  * genMultiAsm - repeat assembly instruction for size of register.
6949  * if endian == 1, then the high byte (i.e base address + size of 
6950  * register) is used first else the low byte is used first;
6951  *-----------------------------------------------------------------*/
6952 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
6953 {
6954
6955   int offset = 0;
6956
6957   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6958
6959   if(!reg)
6960     return;
6961
6962   if(!endian) {
6963     endian = 1;
6964   } else {
6965     endian = -1;
6966     offset = size-1;
6967   }
6968
6969   while(size--) {
6970     emitpcode(poc,    popGet(AOP(reg),offset));
6971     offset += endian;
6972   }
6973
6974 }
6975 /*-----------------------------------------------------------------*/
6976 /* genLeftShift - generates code for left shifting                 */
6977 /*-----------------------------------------------------------------*/
6978 static void genLeftShift (iCode *ic)
6979 {
6980     operand *left,*right, *result;
6981     int size, offset;
6982     char *l;
6983     symbol *tlbl , *tlbl1;
6984
6985     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6986
6987     right = IC_RIGHT(ic);
6988     left  = IC_LEFT(ic);
6989     result = IC_RESULT(ic);
6990
6991     aopOp(right,ic,FALSE);
6992
6993     /* if the shift count is known then do it 
6994     as efficiently as possible */
6995     if (AOP_TYPE(right) == AOP_LIT) {
6996         genLeftShiftLiteral (left,right,result,ic);
6997         return ;
6998     }
6999
7000     /* shift count is unknown then we have to form 
7001     a loop get the loop count in B : Note: we take
7002     only the lower order byte since shifting
7003     more that 32 bits make no sense anyway, ( the
7004     largest size of an object can be only 32 bits ) */  
7005
7006     
7007     aopOp(left,ic,FALSE);
7008     aopOp(result,ic,FALSE);
7009
7010     /* now move the left to the result if they are not the
7011     same */
7012     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7013         AOP_SIZE(result) > 1) {
7014
7015         size = AOP_SIZE(result);
7016         offset=0;
7017         while (size--) {
7018             l = aopGet(AOP(left),offset,FALSE,TRUE);
7019             if (*l == '@' && (IS_AOP_PREG(result))) {
7020
7021                 pic14_emitcode("mov","a,%s",l);
7022                 aopPut(AOP(result),"a",offset);
7023             } else
7024                 aopPut(AOP(result),l,offset);
7025             offset++;
7026         }
7027     }
7028
7029     size = AOP_SIZE(result);
7030
7031     /* if it is only one byte then */
7032     if (size == 1) {
7033       if(optimized_for_speed) {
7034         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7035         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7036         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7037         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7038         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7039         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7040         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7041         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7042         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7043         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7044         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7045         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7046       } else {
7047
7048         tlbl = newiTempLabel(NULL);
7049         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7050           emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7051           emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7052         }
7053
7054         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7055         emitpcode(POC_RRF,    popGet(AOP(result),0));
7056         emitpLabel(tlbl->key);
7057         emitpcode(POC_RLF,    popGet(AOP(result),0));
7058         emitpcode(POC_ADDLW,  popGetLit(1));
7059         emitSKPC;
7060         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7061       }
7062       goto release ;
7063     }
7064     
7065     if (pic14_sameRegs(AOP(left),AOP(result))) {
7066
7067       tlbl = newiTempLabel(NULL);
7068       emitpcode(POC_COMFW,  popGet(AOP(right),0));
7069       genMultiAsm(POC_RRF, result, size,1);
7070       emitpLabel(tlbl->key);
7071       genMultiAsm(POC_RLF, result, size,0);
7072       emitpcode(POC_ADDLW,  popGetLit(1));
7073       emitSKPC;
7074       emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7075       goto release;
7076     }
7077
7078     tlbl = newiTempLabel(NULL);
7079     offset = 0 ;   
7080     tlbl1 = newiTempLabel(NULL);
7081
7082     reAdjustPreg(AOP(result));    
7083     
7084     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7085     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7086     l = aopGet(AOP(result),offset,FALSE,FALSE);
7087     MOVA(l);
7088     pic14_emitcode("add","a,acc");         
7089     aopPut(AOP(result),"a",offset++);
7090     while (--size) {
7091         l = aopGet(AOP(result),offset,FALSE,FALSE);
7092         MOVA(l);
7093         pic14_emitcode("rlc","a");         
7094         aopPut(AOP(result),"a",offset++);
7095     }
7096     reAdjustPreg(AOP(result));
7097
7098     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7099     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7100 release:
7101     freeAsmop (right,NULL,ic,TRUE);
7102     freeAsmop(left,NULL,ic,TRUE);
7103     freeAsmop(result,NULL,ic,TRUE);
7104 }
7105
7106 /*-----------------------------------------------------------------*/
7107 /* genrshOne - right shift a one byte quantity by known count      */
7108 /*-----------------------------------------------------------------*/
7109 static void genrshOne (operand *result, operand *left,
7110                        int shCount, int sign)
7111 {
7112     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7113     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7114 }
7115
7116 /*-----------------------------------------------------------------*/
7117 /* genrshTwo - right shift two bytes by known amount != 0          */
7118 /*-----------------------------------------------------------------*/
7119 static void genrshTwo (operand *result,operand *left,
7120                        int shCount, int sign)
7121 {
7122   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7123   /* if shCount >= 8 */
7124   if (shCount >= 8) {
7125     shCount -= 8 ;
7126     if (shCount)
7127       shiftR1Left2Result(left, MSB16, result, LSB,
7128                          shCount, sign);
7129     else
7130       movLeft2Result(left, MSB16, result, LSB, sign);
7131
7132     emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7133
7134     if(sign) {
7135       emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7136       emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7137     }
7138   }
7139
7140   /*  1 <= shCount <= 7 */
7141   else
7142     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7143 }
7144
7145 /*-----------------------------------------------------------------*/
7146 /* shiftRLong - shift right one long from left to result           */
7147 /* offl = LSB or MSB16                                             */
7148 /*-----------------------------------------------------------------*/
7149 static void shiftRLong (operand *left, int offl,
7150                         operand *result, int sign)
7151 {
7152     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7153     if(!sign)
7154         pic14_emitcode("clr","c");
7155     MOVA(aopGet(AOP(left),MSB32,FALSE,FALSE));
7156     if(sign)
7157         pic14_emitcode("mov","c,acc.7");
7158     pic14_emitcode("rrc","a");
7159     aopPut(AOP(result),"a",MSB32-offl);
7160     if(offl == MSB16)
7161         /* add sign of "a" */
7162         addSign(result, MSB32, sign);
7163
7164     MOVA(aopGet(AOP(left),MSB24,FALSE,FALSE));
7165     pic14_emitcode("rrc","a");
7166     aopPut(AOP(result),"a",MSB24-offl);
7167
7168     MOVA(aopGet(AOP(left),MSB16,FALSE,FALSE));
7169     pic14_emitcode("rrc","a");
7170     aopPut(AOP(result),"a",MSB16-offl);
7171
7172     if(offl == LSB){
7173         MOVA(aopGet(AOP(left),LSB,FALSE,FALSE));
7174         pic14_emitcode("rrc","a");
7175         aopPut(AOP(result),"a",LSB);
7176     }
7177 }
7178
7179 /*-----------------------------------------------------------------*/
7180 /* genrshFour - shift four byte by a known amount != 0             */
7181 /*-----------------------------------------------------------------*/
7182 static void genrshFour (operand *result, operand *left,
7183                         int shCount, int sign)
7184 {
7185     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7186     /* if shifting more that 3 bytes */
7187     if(shCount >= 24 ) {
7188         shCount -= 24;
7189         if(shCount)
7190             shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7191         else
7192             movLeft2Result(left, MSB32, result, LSB, sign);
7193         addSign(result, MSB16, sign);
7194     }
7195     else if(shCount >= 16){
7196         shCount -= 16;
7197         if(shCount)
7198             shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7199         else{
7200             movLeft2Result(left, MSB24, result, LSB, 0);
7201             movLeft2Result(left, MSB32, result, MSB16, sign);
7202         }
7203         addSign(result, MSB24, sign);
7204     }
7205     else if(shCount >= 8){
7206         shCount -= 8;
7207         if(shCount == 1)
7208             shiftRLong(left, MSB16, result, sign);
7209         else if(shCount == 0){
7210             movLeft2Result(left, MSB16, result, LSB, 0);
7211             movLeft2Result(left, MSB24, result, MSB16, 0);
7212             movLeft2Result(left, MSB32, result, MSB24, sign);
7213             addSign(result, MSB32, sign);
7214         }
7215         else{
7216             shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7217             shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7218             /* the last shift is signed */
7219             shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7220             addSign(result, MSB32, sign);
7221         }
7222     }
7223     else{   /* 1 <= shCount <= 7 */
7224         if(shCount <= 2){
7225             shiftRLong(left, LSB, result, sign);
7226             if(shCount == 2)
7227                 shiftRLong(result, LSB, result, sign);
7228         }
7229         else{
7230             shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7231             shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7232             shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7233         }
7234     }
7235 }
7236
7237 /*-----------------------------------------------------------------*/
7238 /* genRightShiftLiteral - right shifting by known count            */
7239 /*-----------------------------------------------------------------*/
7240 static void genRightShiftLiteral (operand *left,
7241                                   operand *right,
7242                                   operand *result,
7243                                   iCode *ic,
7244                                   int sign)
7245 {    
7246     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7247     int size;
7248
7249     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7250     freeAsmop(right,NULL,ic,TRUE);
7251
7252     aopOp(left,ic,FALSE);
7253     aopOp(result,ic,FALSE);
7254
7255 #if VIEW_SIZE
7256     pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7257              AOP_SIZE(left));
7258 #endif
7259
7260     size = pic14_getDataSize(left);
7261     /* test the LEFT size !!! */
7262
7263     /* I suppose that the left size >= result size */
7264     if(shCount == 0){
7265         size = pic14_getDataSize(result);
7266         while(size--)
7267             movLeft2Result(left, size, result, size, 0);
7268     }
7269
7270     else if(shCount >= (size * 8)){
7271         if(sign)
7272             /* get sign in acc.7 */
7273             MOVA(aopGet(AOP(left),size-1,FALSE,FALSE));
7274         addSign(result, LSB, sign);
7275     } else{
7276         switch (size) {
7277             case 1:
7278                 genrshOne (result,left,shCount,sign);
7279                 break;
7280
7281             case 2:
7282                 genrshTwo (result,left,shCount,sign);
7283                 break;
7284
7285             case 4:
7286                 genrshFour (result,left,shCount,sign);
7287                 break;
7288             default :
7289                 break;
7290         }
7291
7292         freeAsmop(left,NULL,ic,TRUE);
7293         freeAsmop(result,NULL,ic,TRUE);
7294     }
7295 }
7296
7297 /*-----------------------------------------------------------------*/
7298 /* genSignedRightShift - right shift of signed number              */
7299 /*-----------------------------------------------------------------*/
7300 static void genSignedRightShift (iCode *ic)
7301 {
7302     operand *right, *left, *result;
7303     int size, offset;
7304     char *l;
7305     symbol *tlbl, *tlbl1 ;
7306
7307     /* we do it the hard way put the shift count in b
7308     and loop thru preserving the sign */
7309     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7310
7311     right = IC_RIGHT(ic);
7312     left  = IC_LEFT(ic);
7313     result = IC_RESULT(ic);
7314
7315     aopOp(right,ic,FALSE);  
7316
7317
7318     if ( AOP_TYPE(right) == AOP_LIT) {
7319         genRightShiftLiteral (left,right,result,ic,1);
7320         return ;
7321     }
7322         /* shift count is unknown then we have to form 
7323        a loop get the loop count in B : Note: we take
7324        only the lower order byte since shifting
7325        more that 32 bits make no sense anyway, ( the
7326        largest size of an object can be only 32 bits ) */  
7327
7328     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7329     pic14_emitcode("inc","b");
7330     freeAsmop (right,NULL,ic,TRUE);
7331     aopOp(left,ic,FALSE);
7332     aopOp(result,ic,FALSE);
7333
7334     /* now move the left to the result if they are not the
7335     same */
7336     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7337         AOP_SIZE(result) > 1) {
7338
7339         size = AOP_SIZE(result);
7340         offset=0;
7341         while (size--) {
7342             l = aopGet(AOP(left),offset,FALSE,TRUE);
7343             if (*l == '@' && IS_AOP_PREG(result)) {
7344
7345                 pic14_emitcode("mov","a,%s",l);
7346                 aopPut(AOP(result),"a",offset);
7347             } else
7348                 aopPut(AOP(result),l,offset);
7349             offset++;
7350         }
7351     }
7352
7353     /* mov the highest order bit to OVR */    
7354     tlbl = newiTempLabel(NULL);
7355     tlbl1= newiTempLabel(NULL);
7356
7357     size = AOP_SIZE(result);
7358     offset = size - 1;
7359     pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7360     pic14_emitcode("rlc","a");
7361     pic14_emitcode("mov","ov,c");
7362     /* if it is only one byte then */
7363     if (size == 1) {
7364         l = aopGet(AOP(left),0,FALSE,FALSE);
7365         MOVA(l);
7366         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7367         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7368         pic14_emitcode("mov","c,ov");
7369         pic14_emitcode("rrc","a");
7370         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7371         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7372         aopPut(AOP(result),"a",0);
7373         goto release ;
7374     }
7375
7376     reAdjustPreg(AOP(result));
7377     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7378     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7379     pic14_emitcode("mov","c,ov");
7380     while (size--) {
7381         l = aopGet(AOP(result),offset,FALSE,FALSE);
7382         MOVA(l);
7383         pic14_emitcode("rrc","a");         
7384         aopPut(AOP(result),"a",offset--);
7385     }
7386     reAdjustPreg(AOP(result));
7387     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7388     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7389
7390 release:
7391     freeAsmop(left,NULL,ic,TRUE);
7392     freeAsmop(result,NULL,ic,TRUE);
7393 }
7394
7395 /*-----------------------------------------------------------------*/
7396 /* genRightShift - generate code for right shifting                */
7397 /*-----------------------------------------------------------------*/
7398 static void genRightShift (iCode *ic)
7399 {
7400     operand *right, *left, *result;
7401     sym_link *retype ;
7402     int size, offset;
7403     char *l;
7404     symbol *tlbl, *tlbl1 ;
7405
7406     /* if signed then we do it the hard way preserve the
7407     sign bit moving it inwards */
7408     retype = getSpec(operandType(IC_RESULT(ic)));
7409     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7410
7411     if (!SPEC_USIGN(retype)) {
7412         genSignedRightShift (ic);
7413         return ;
7414     }
7415
7416     /* signed & unsigned types are treated the same : i.e. the
7417     signed is NOT propagated inwards : quoting from the
7418     ANSI - standard : "for E1 >> E2, is equivalent to division
7419     by 2**E2 if unsigned or if it has a non-negative value,
7420     otherwise the result is implementation defined ", MY definition
7421     is that the sign does not get propagated */
7422
7423     right = IC_RIGHT(ic);
7424     left  = IC_LEFT(ic);
7425     result = IC_RESULT(ic);
7426
7427     aopOp(right,ic,FALSE);
7428
7429     /* if the shift count is known then do it 
7430     as efficiently as possible */
7431     if (AOP_TYPE(right) == AOP_LIT) {
7432         genRightShiftLiteral (left,right,result,ic, 0);
7433         return ;
7434     }
7435
7436     /* shift count is unknown then we have to form 
7437     a loop get the loop count in B : Note: we take
7438     only the lower order byte since shifting
7439     more that 32 bits make no sense anyway, ( the
7440     largest size of an object can be only 32 bits ) */  
7441
7442     pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7443     pic14_emitcode("inc","b");
7444     aopOp(left,ic,FALSE);
7445     aopOp(result,ic,FALSE);
7446
7447     /* now move the left to the result if they are not the
7448     same */
7449     if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7450         AOP_SIZE(result) > 1) {
7451
7452         size = AOP_SIZE(result);
7453         offset=0;
7454         while (size--) {
7455             l = aopGet(AOP(left),offset,FALSE,TRUE);
7456             if (*l == '@' && IS_AOP_PREG(result)) {
7457
7458                 pic14_emitcode("mov","a,%s",l);
7459                 aopPut(AOP(result),"a",offset);
7460             } else
7461                 aopPut(AOP(result),l,offset);
7462             offset++;
7463         }
7464     }
7465
7466     tlbl = newiTempLabel(NULL);
7467     tlbl1= newiTempLabel(NULL);
7468     size = AOP_SIZE(result);
7469     offset = size - 1;
7470
7471     /* if it is only one byte then */
7472     if (size == 1) {
7473 /*
7474         l = aopGet(AOP(left),0,FALSE,FALSE);
7475         MOVA(l);
7476         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7477         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7478         CLRC;
7479         pic14_emitcode("rrc","a");
7480         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7481         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7482         aopPut(AOP(result),"a",0);
7483 */
7484         tlbl = newiTempLabel(NULL);
7485         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7486           emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7487           emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7488         }
7489
7490         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7491         emitpcode(POC_RLF,    popGet(AOP(result),0));
7492         emitpLabel(tlbl->key);
7493         emitpcode(POC_RRF,    popGet(AOP(result),0));
7494         emitpcode(POC_ADDLW,  popGetLit(1));
7495         emitSKPC;
7496         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7497
7498         goto release ;
7499     }
7500
7501     reAdjustPreg(AOP(result));
7502     pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7503     pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7504     CLRC;
7505     while (size--) {
7506         l = aopGet(AOP(result),offset,FALSE,FALSE);
7507         MOVA(l);
7508         pic14_emitcode("rrc","a");         
7509         aopPut(AOP(result),"a",offset--);
7510     }
7511     reAdjustPreg(AOP(result));
7512
7513     pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7514     pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7515
7516 release:
7517     freeAsmop(left,NULL,ic,TRUE);
7518     freeAsmop (right,NULL,ic,TRUE);
7519     freeAsmop(result,NULL,ic,TRUE);
7520 }
7521
7522 /*-----------------------------------------------------------------*/
7523 /* genUnpackBits - generates code for unpacking bits               */
7524 /*-----------------------------------------------------------------*/
7525 static void genUnpackBits (operand *result, char *rname, int ptype)
7526 {    
7527     int shCnt ;
7528     int rlen = 0 ;
7529     sym_link *etype;
7530     int offset = 0 ;
7531
7532     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7533     etype = getSpec(operandType(result));
7534
7535     /* read the first byte  */
7536     switch (ptype) {
7537
7538     case POINTER:
7539     case IPOINTER:
7540         pic14_emitcode("mov","a,@%s",rname);
7541         break;
7542         
7543     case PPOINTER:
7544         pic14_emitcode("movx","a,@%s",rname);
7545         break;
7546         
7547     case FPOINTER:
7548         pic14_emitcode("movx","a,@dptr");
7549         break;
7550
7551     case CPOINTER:
7552         pic14_emitcode("clr","a");
7553         pic14_emitcode("movc","a","@a+dptr");
7554         break;
7555
7556     case GPOINTER:
7557         pic14_emitcode("lcall","__gptrget");
7558         break;
7559     }
7560
7561     /* if we have bitdisplacement then it fits   */
7562     /* into this byte completely or if length is */
7563     /* less than a byte                          */
7564     if ((shCnt = SPEC_BSTR(etype)) || 
7565         (SPEC_BLEN(etype) <= 8))  {
7566
7567         /* shift right acc */
7568         AccRsh(shCnt);
7569
7570         pic14_emitcode("anl","a,#0x%02x",
7571                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
7572         aopPut(AOP(result),"a",offset);
7573         return ;
7574     }
7575
7576     /* bit field did not fit in a byte  */
7577     rlen = SPEC_BLEN(etype) - 8;
7578     aopPut(AOP(result),"a",offset++);
7579
7580     while (1)  {
7581
7582         switch (ptype) {
7583         case POINTER:
7584         case IPOINTER:
7585             pic14_emitcode("inc","%s",rname);
7586             pic14_emitcode("mov","a,@%s",rname);
7587             break;
7588             
7589         case PPOINTER:
7590             pic14_emitcode("inc","%s",rname);
7591             pic14_emitcode("movx","a,@%s",rname);
7592             break;
7593
7594         case FPOINTER:
7595             pic14_emitcode("inc","dptr");
7596             pic14_emitcode("movx","a,@dptr");
7597             break;
7598             
7599         case CPOINTER:
7600             pic14_emitcode("clr","a");
7601             pic14_emitcode("inc","dptr");
7602             pic14_emitcode("movc","a","@a+dptr");
7603             break;
7604             
7605         case GPOINTER:
7606             pic14_emitcode("inc","dptr");
7607             pic14_emitcode("lcall","__gptrget");
7608             break;
7609         }
7610
7611         rlen -= 8;            
7612         /* if we are done */
7613         if ( rlen <= 0 )
7614             break ;
7615         
7616         aopPut(AOP(result),"a",offset++);
7617                               
7618     }
7619     
7620     if (rlen) {
7621         pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
7622         aopPut(AOP(result),"a",offset);        
7623     }
7624     
7625     return ;
7626 }
7627
7628
7629 /*-----------------------------------------------------------------*/
7630 /* genDataPointerGet - generates code when ptr offset is known     */
7631 /*-----------------------------------------------------------------*/
7632 static void genDataPointerGet (operand *left, 
7633                                operand *result, 
7634                                iCode *ic)
7635 {
7636   int size , offset = 0;
7637
7638
7639   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7640
7641
7642   /* optimization - most of the time, left and result are the same
7643    * address, but different types. for the pic code, we could omit
7644    * the following
7645    */
7646
7647   aopOp(result,ic,TRUE);
7648
7649   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7650
7651   emitpcode(POC_MOVFW, popGet(AOP(left),0));
7652
7653   size = AOP_SIZE(result);
7654
7655   while (size--) {
7656     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
7657     offset++;
7658   }
7659
7660   freeAsmop(left,NULL,ic,TRUE);
7661   freeAsmop(result,NULL,ic,TRUE);
7662 }
7663
7664 /*-----------------------------------------------------------------*/
7665 /* genNearPointerGet - pic14_emitcode for near pointer fetch             */
7666 /*-----------------------------------------------------------------*/
7667 static void genNearPointerGet (operand *left, 
7668                                operand *result, 
7669                                iCode *ic)
7670 {
7671     asmop *aop = NULL;
7672     regs *preg = NULL ;
7673     char *rname ;
7674     sym_link *rtype, *retype;
7675     sym_link *ltype = operandType(left);    
7676     char buffer[80];
7677
7678     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7679
7680     rtype = operandType(result);
7681     retype= getSpec(rtype);
7682     
7683     aopOp(left,ic,FALSE);
7684     
7685     /* if left is rematerialisable and
7686        result is not bit variable type and
7687        the left is pointer to data space i.e
7688        lower 128 bytes of space */
7689     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
7690         !IS_BITVAR(retype)         &&
7691         DCL_TYPE(ltype) == POINTER) {
7692       //genDataPointerGet (left,result,ic);
7693         return ;
7694     }
7695     
7696     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7697
7698         /* if the value is already in a pointer register
7699        then don't need anything more */
7700     if (!AOP_INPREG(AOP(left))) {
7701         /* otherwise get a free pointer register */
7702     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7703         aop = newAsmop(0);
7704         preg = getFreePtr(ic,&aop,FALSE);
7705         pic14_emitcode("mov","%s,%s",
7706                 preg->name,
7707                 aopGet(AOP(left),0,FALSE,TRUE));
7708         rname = preg->name ;
7709     } else
7710         rname = aopGet(AOP(left),0,FALSE,FALSE);
7711     
7712     freeAsmop(left,NULL,ic,TRUE);
7713     aopOp (result,ic,FALSE);
7714     
7715       /* if bitfield then unpack the bits */
7716     if (IS_BITVAR(retype)) 
7717         genUnpackBits (result,rname,POINTER);
7718     else {
7719         /* we have can just get the values */
7720         int size = AOP_SIZE(result);
7721         int offset = 0 ;        
7722         
7723     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7724         while (size--) {
7725             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
7726
7727                 pic14_emitcode("mov","a,@%s",rname);
7728                 aopPut(AOP(result),"a",offset);
7729             } else {
7730                 sprintf(buffer,"@%s",rname);
7731                 aopPut(AOP(result),buffer,offset);
7732             }
7733             offset++ ;
7734             if (size)
7735                 pic14_emitcode("inc","%s",rname);
7736         }
7737     }
7738
7739     /* now some housekeeping stuff */
7740     if (aop) {
7741         /* we had to allocate for this iCode */
7742     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7743         freeAsmop(NULL,aop,ic,TRUE);
7744     } else { 
7745         /* we did not allocate which means left
7746            already in a pointer register, then
7747            if size > 0 && this could be used again
7748            we have to point it back to where it 
7749            belongs */
7750     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7751         if (AOP_SIZE(result) > 1 &&
7752             !OP_SYMBOL(left)->remat &&
7753             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7754               ic->depth )) {
7755             int size = AOP_SIZE(result) - 1;
7756             while (size--)
7757                 pic14_emitcode("dec","%s",rname);
7758         }
7759     }
7760
7761     /* done */
7762     freeAsmop(result,NULL,ic,TRUE);
7763      
7764 }
7765
7766 /*-----------------------------------------------------------------*/
7767 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
7768 /*-----------------------------------------------------------------*/
7769 static void genPagedPointerGet (operand *left, 
7770                                operand *result, 
7771                                iCode *ic)
7772 {
7773     asmop *aop = NULL;
7774     regs *preg = NULL ;
7775     char *rname ;
7776     sym_link *rtype, *retype;    
7777
7778     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7779
7780     rtype = operandType(result);
7781     retype= getSpec(rtype);
7782     
7783     aopOp(left,ic,FALSE);
7784
7785   /* if the value is already in a pointer register
7786        then don't need anything more */
7787     if (!AOP_INPREG(AOP(left))) {
7788         /* otherwise get a free pointer register */
7789         aop = newAsmop(0);
7790         preg = getFreePtr(ic,&aop,FALSE);
7791         pic14_emitcode("mov","%s,%s",
7792                 preg->name,
7793                 aopGet(AOP(left),0,FALSE,TRUE));
7794         rname = preg->name ;
7795     } else
7796         rname = aopGet(AOP(left),0,FALSE,FALSE);
7797     
7798     freeAsmop(left,NULL,ic,TRUE);
7799     aopOp (result,ic,FALSE);
7800
7801     /* if bitfield then unpack the bits */
7802     if (IS_BITVAR(retype)) 
7803         genUnpackBits (result,rname,PPOINTER);
7804     else {
7805         /* we have can just get the values */
7806         int size = AOP_SIZE(result);
7807         int offset = 0 ;        
7808         
7809         while (size--) {
7810             
7811             pic14_emitcode("movx","a,@%s",rname);
7812             aopPut(AOP(result),"a",offset);
7813             
7814             offset++ ;
7815             
7816             if (size)
7817                 pic14_emitcode("inc","%s",rname);
7818         }
7819     }
7820
7821     /* now some housekeeping stuff */
7822     if (aop) {
7823         /* we had to allocate for this iCode */
7824         freeAsmop(NULL,aop,ic,TRUE);
7825     } else { 
7826         /* we did not allocate which means left
7827            already in a pointer register, then
7828            if size > 0 && this could be used again
7829            we have to point it back to where it 
7830            belongs */
7831         if (AOP_SIZE(result) > 1 &&
7832             !OP_SYMBOL(left)->remat &&
7833             ( OP_SYMBOL(left)->liveTo > ic->seq ||
7834               ic->depth )) {
7835             int size = AOP_SIZE(result) - 1;
7836             while (size--)
7837                 pic14_emitcode("dec","%s",rname);
7838         }
7839     }
7840
7841     /* done */
7842     freeAsmop(result,NULL,ic,TRUE);
7843     
7844         
7845 }
7846
7847 /*-----------------------------------------------------------------*/
7848 /* genFarPointerGet - gget value from far space                    */
7849 /*-----------------------------------------------------------------*/
7850 static void genFarPointerGet (operand *left,
7851                               operand *result, iCode *ic)
7852 {
7853     int size, offset ;
7854     sym_link *retype = getSpec(operandType(result));
7855
7856     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7857
7858     aopOp(left,ic,FALSE);
7859
7860     /* if the operand is already in dptr 
7861     then we do nothing else we move the value to dptr */
7862     if (AOP_TYPE(left) != AOP_STR) {
7863         /* if this is remateriazable */
7864         if (AOP_TYPE(left) == AOP_IMMD)
7865             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7866         else { /* we need to get it byte by byte */
7867             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7868             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7869             if (options.model == MODEL_FLAT24)
7870             {
7871                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7872             }
7873         }
7874     }
7875     /* so dptr know contains the address */
7876     freeAsmop(left,NULL,ic,TRUE);
7877     aopOp(result,ic,FALSE);
7878
7879     /* if bit then unpack */
7880     if (IS_BITVAR(retype)) 
7881         genUnpackBits(result,"dptr",FPOINTER);
7882     else {
7883         size = AOP_SIZE(result);
7884         offset = 0 ;
7885
7886         while (size--) {
7887             pic14_emitcode("movx","a,@dptr");
7888             aopPut(AOP(result),"a",offset++);
7889             if (size)
7890                 pic14_emitcode("inc","dptr");
7891         }
7892     }
7893
7894     freeAsmop(result,NULL,ic,TRUE);
7895 }
7896 #if 0
7897 /*-----------------------------------------------------------------*/
7898 /* genCodePointerGet - get value from code space                  */
7899 /*-----------------------------------------------------------------*/
7900 static void genCodePointerGet (operand *left,
7901                                 operand *result, iCode *ic)
7902 {
7903     int size, offset ;
7904     sym_link *retype = getSpec(operandType(result));
7905
7906     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7907
7908     aopOp(left,ic,FALSE);
7909
7910     /* if the operand is already in dptr 
7911     then we do nothing else we move the value to dptr */
7912     if (AOP_TYPE(left) != AOP_STR) {
7913         /* if this is remateriazable */
7914         if (AOP_TYPE(left) == AOP_IMMD)
7915             pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7916         else { /* we need to get it byte by byte */
7917             pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
7918             pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
7919             if (options.model == MODEL_FLAT24)
7920             {
7921                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
7922             }
7923         }
7924     }
7925     /* so dptr know contains the address */
7926     freeAsmop(left,NULL,ic,TRUE);
7927     aopOp(result,ic,FALSE);
7928
7929     /* if bit then unpack */
7930     if (IS_BITVAR(retype)) 
7931         genUnpackBits(result,"dptr",CPOINTER);
7932     else {
7933         size = AOP_SIZE(result);
7934         offset = 0 ;
7935
7936         while (size--) {
7937             pic14_emitcode("clr","a");
7938             pic14_emitcode("movc","a,@a+dptr");
7939             aopPut(AOP(result),"a",offset++);
7940             if (size)
7941                 pic14_emitcode("inc","dptr");
7942         }
7943     }
7944
7945     freeAsmop(result,NULL,ic,TRUE);
7946 }
7947 #endif
7948 /*-----------------------------------------------------------------*/
7949 /* genGenPointerGet - gget value from generic pointer space        */
7950 /*-----------------------------------------------------------------*/
7951 static void genGenPointerGet (operand *left,
7952                               operand *result, iCode *ic)
7953 {
7954   int size, offset ;
7955   sym_link *retype = getSpec(operandType(result));
7956
7957   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7958   aopOp(left,ic,FALSE);
7959   aopOp(result,ic,FALSE);
7960
7961
7962   DEBUGpic14_AopType(__LINE__,left,NULL,result);
7963
7964   /* if the operand is already in dptr 
7965      then we do nothing else we move the value to dptr */
7966   //  if (AOP_TYPE(left) != AOP_STR) {
7967     /* if this is remateriazable */
7968     if (AOP_TYPE(left) == AOP_IMMD) {
7969       pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
7970       pic14_emitcode("mov","b,#%d",pointerCode(retype));
7971     }
7972     else { /* we need to get it byte by byte */
7973
7974       emitpcode(POC_MOVFW,popGet(AOP(left),0));
7975       emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
7976
7977       size = AOP_SIZE(result);
7978       offset = 0 ;
7979
7980       while(size--) {
7981         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
7982         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
7983         if(size)
7984           emitpcode(POC_INCF,popCopyReg(&pc_fsr));
7985       }
7986       goto release;
7987     }
7988     //}
7989   /* so dptr know contains the address */
7990
7991   /* if bit then unpack */
7992   //if (IS_BITVAR(retype)) 
7993   //  genUnpackBits(result,"dptr",GPOINTER);
7994
7995  release:
7996   freeAsmop(left,NULL,ic,TRUE);
7997   freeAsmop(result,NULL,ic,TRUE);
7998
7999 }
8000
8001 /*-----------------------------------------------------------------*/
8002 /* genConstPointerGet - get value from const generic pointer space */
8003 /*-----------------------------------------------------------------*/
8004 static void genConstPointerGet (operand *left,
8005                                 operand *result, iCode *ic)
8006 {
8007   //sym_link *retype = getSpec(operandType(result));
8008   symbol *albl = newiTempLabel(NULL);
8009   symbol *blbl = newiTempLabel(NULL);
8010   PIC_OPCODE poc;
8011
8012   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8013   aopOp(left,ic,FALSE);
8014   aopOp(result,ic,FALSE);
8015
8016
8017   DEBUGpic14_AopType(__LINE__,left,NULL,result);
8018
8019   DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8020
8021   emitpcode(POC_CALL,popGetLabel(albl->key));
8022   emitpcode(POC_GOTO,popGetLabel(blbl->key));
8023   emitpLabel(albl->key);
8024
8025   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8026     
8027   emitpcode(poc,popGet(AOP(left),1));
8028   emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8029   emitpcode(poc,popGet(AOP(left),0));
8030   emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8031
8032   emitpLabel(blbl->key);
8033
8034   emitpcode(POC_MOVWF,popGet(AOP(result),0));
8035
8036
8037   freeAsmop(left,NULL,ic,TRUE);
8038   freeAsmop(result,NULL,ic,TRUE);
8039
8040 }
8041 /*-----------------------------------------------------------------*/
8042 /* genPointerGet - generate code for pointer get                   */
8043 /*-----------------------------------------------------------------*/
8044 static void genPointerGet (iCode *ic)
8045 {
8046     operand *left, *result ;
8047     sym_link *type, *etype;
8048     int p_type;
8049
8050     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8051
8052     left = IC_LEFT(ic);
8053     result = IC_RESULT(ic) ;
8054
8055     /* depending on the type of pointer we need to
8056     move it to the correct pointer register */
8057     type = operandType(left);
8058     etype = getSpec(type);
8059
8060     if (IS_PTR_CONST(type))
8061       DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8062
8063     /* if left is of type of pointer then it is simple */
8064     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8065         p_type = DCL_TYPE(type);
8066     else {
8067         /* we have to go by the storage class */
8068         p_type = PTR_TYPE(SPEC_OCLS(etype));
8069
8070         DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8071
8072         if (SPEC_OCLS(etype)->codesp ) {
8073           DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8074           //p_type = CPOINTER ; 
8075         }
8076         else
8077             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8078               DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8079                /*p_type = FPOINTER ;*/ 
8080             else
8081                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8082                   DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8083 /*                  p_type = PPOINTER; */
8084                 else
8085                     if (SPEC_OCLS(etype) == idata )
8086                       DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8087 /*                      p_type = IPOINTER; */
8088                     else
8089                       DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8090 /*                      p_type = POINTER ; */
8091     }
8092
8093     /* now that we have the pointer type we assign
8094     the pointer values */
8095     switch (p_type) {
8096
8097     case POINTER:       
8098     case IPOINTER:
8099         genNearPointerGet (left,result,ic);
8100         break;
8101
8102     case PPOINTER:
8103         genPagedPointerGet(left,result,ic);
8104         break;
8105
8106     case FPOINTER:
8107         genFarPointerGet (left,result,ic);
8108         break;
8109
8110     case CPOINTER:
8111         genConstPointerGet (left,result,ic);
8112         //pic14_emitcodePointerGet (left,result,ic);
8113         break;
8114
8115     case GPOINTER:
8116       if (IS_PTR_CONST(type))
8117         genConstPointerGet (left,result,ic);
8118       else
8119         genGenPointerGet (left,result,ic);
8120       break;
8121     }
8122
8123 }
8124
8125 /*-----------------------------------------------------------------*/
8126 /* genPackBits - generates code for packed bit storage             */
8127 /*-----------------------------------------------------------------*/
8128 static void genPackBits (sym_link    *etype ,
8129                          operand *right ,
8130                          char *rname, int p_type)
8131 {
8132     int shCount = 0 ;
8133     int offset = 0  ;
8134     int rLen = 0 ;
8135     int blen, bstr ;   
8136     char *l ;
8137
8138     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8139     blen = SPEC_BLEN(etype);
8140     bstr = SPEC_BSTR(etype);
8141
8142     l = aopGet(AOP(right),offset++,FALSE,FALSE);
8143     MOVA(l);   
8144
8145     /* if the bit lenth is less than or    */
8146     /* it exactly fits a byte then         */
8147     if (SPEC_BLEN(etype) <= 8 )  {
8148         shCount = SPEC_BSTR(etype) ;
8149
8150         /* shift left acc */
8151         AccLsh(shCount);
8152
8153         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8154
8155
8156             switch (p_type) {
8157                 case POINTER:
8158                     pic14_emitcode ("mov","b,a");
8159                     pic14_emitcode("mov","a,@%s",rname);
8160                     break;
8161
8162                 case FPOINTER:
8163                     pic14_emitcode ("mov","b,a");
8164                     pic14_emitcode("movx","a,@dptr");
8165                     break;
8166
8167                 case GPOINTER:
8168                     pic14_emitcode ("push","b");
8169                     pic14_emitcode ("push","acc");
8170                     pic14_emitcode ("lcall","__gptrget");
8171                     pic14_emitcode ("pop","b");
8172                     break;
8173             }
8174
8175             pic14_emitcode ("anl","a,#0x%02x",(unsigned char)
8176                       ((unsigned char)(0xFF << (blen+bstr)) | 
8177                        (unsigned char)(0xFF >> (8-bstr)) ) );
8178             pic14_emitcode ("orl","a,b");
8179             if (p_type == GPOINTER)
8180                 pic14_emitcode("pop","b");
8181         }
8182     }
8183
8184     switch (p_type) {
8185         case POINTER:
8186             pic14_emitcode("mov","@%s,a",rname);
8187             break;
8188
8189         case FPOINTER:
8190             pic14_emitcode("movx","@dptr,a");
8191             break;
8192
8193         case GPOINTER:
8194             DEBUGpic14_emitcode(";lcall","__gptrput");
8195             break;
8196     }
8197
8198     /* if we r done */
8199     if ( SPEC_BLEN(etype) <= 8 )
8200         return ;
8201
8202     pic14_emitcode("inc","%s",rname);
8203     rLen = SPEC_BLEN(etype) ;     
8204
8205     /* now generate for lengths greater than one byte */
8206     while (1) {
8207
8208         l = aopGet(AOP(right),offset++,FALSE,TRUE);
8209
8210         rLen -= 8 ;
8211         if (rLen <= 0 )
8212             break ;
8213
8214         switch (p_type) {
8215             case POINTER:
8216                 if (*l == '@') {
8217                     MOVA(l);
8218                     pic14_emitcode("mov","@%s,a",rname);
8219                 } else
8220                     pic14_emitcode("mov","@%s,%s",rname,l);
8221                 break;
8222
8223             case FPOINTER:
8224                 MOVA(l);
8225                 pic14_emitcode("movx","@dptr,a");
8226                 break;
8227
8228             case GPOINTER:
8229                 MOVA(l);
8230                 DEBUGpic14_emitcode(";lcall","__gptrput");
8231                 break;  
8232         }   
8233         pic14_emitcode ("inc","%s",rname);
8234     }
8235
8236     MOVA(l);
8237
8238     /* last last was not complete */
8239     if (rLen)   {
8240         /* save the byte & read byte */
8241         switch (p_type) {
8242             case POINTER:
8243                 pic14_emitcode ("mov","b,a");
8244                 pic14_emitcode("mov","a,@%s",rname);
8245                 break;
8246
8247             case FPOINTER:
8248                 pic14_emitcode ("mov","b,a");
8249                 pic14_emitcode("movx","a,@dptr");
8250                 break;
8251
8252             case GPOINTER:
8253                 pic14_emitcode ("push","b");
8254                 pic14_emitcode ("push","acc");
8255                 pic14_emitcode ("lcall","__gptrget");
8256                 pic14_emitcode ("pop","b");
8257                 break;
8258         }
8259
8260         pic14_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8261         pic14_emitcode ("orl","a,b");
8262     }
8263
8264     if (p_type == GPOINTER)
8265         pic14_emitcode("pop","b");
8266
8267     switch (p_type) {
8268
8269     case POINTER:
8270         pic14_emitcode("mov","@%s,a",rname);
8271         break;
8272         
8273     case FPOINTER:
8274         pic14_emitcode("movx","@dptr,a");
8275         break;
8276         
8277     case GPOINTER:
8278         DEBUGpic14_emitcode(";lcall","__gptrput");
8279         break;                  
8280     }
8281 }
8282 /*-----------------------------------------------------------------*/
8283 /* genDataPointerSet - remat pointer to data space                 */
8284 /*-----------------------------------------------------------------*/
8285 static void genDataPointerSet(operand *right,
8286                               operand *result,
8287                               iCode *ic)
8288 {
8289     int size, offset = 0 ;
8290     char *l, buffer[256];
8291
8292     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8293     aopOp(right,ic,FALSE);
8294     
8295     l = aopGet(AOP(result),0,FALSE,TRUE);
8296     size = AOP_SIZE(right);
8297 /*
8298     if ( AOP_TYPE(result) == AOP_PCODE) {
8299       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8300               AOP(result)->aopu.pcop->name,
8301               PCOI(AOP(result)->aopu.pcop)->offset);
8302     }
8303 */
8304
8305     // tsd, was l+1 - the underline `_' prefix was being stripped
8306     while (size--) {
8307       if (offset) {
8308         sprintf(buffer,"(%s + %d)",l,offset);
8309         fprintf(stderr,"oops  %s\n",buffer);
8310       } else
8311         sprintf(buffer,"%s",l);
8312
8313         if (AOP_TYPE(right) == AOP_LIT) {
8314           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8315           lit = lit >> (8*offset);
8316           if(lit&0xff) {
8317             pic14_emitcode("movlw","%d",lit);
8318             pic14_emitcode("movwf","%s",buffer);
8319
8320             emitpcode(POC_MOVLW, popGetLit(lit&0xff));
8321             //emitpcode(POC_MOVWF, popRegFromString(buffer));
8322             emitpcode(POC_MOVWF, popGet(AOP(result),0));
8323
8324           } else {
8325             pic14_emitcode("clrf","%s",buffer);
8326             //emitpcode(POC_CLRF, popRegFromString(buffer));
8327             emitpcode(POC_CLRF, popGet(AOP(result),0));
8328           }
8329         }else {
8330           pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
8331           pic14_emitcode("movwf","%s",buffer);
8332
8333           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8334           //emitpcode(POC_MOVWF, popRegFromString(buffer));
8335           emitpcode(POC_MOVWF, popGet(AOP(result),0));
8336
8337         }
8338
8339         offset++;
8340     }
8341
8342     freeAsmop(right,NULL,ic,TRUE);
8343     freeAsmop(result,NULL,ic,TRUE);
8344 }
8345
8346 /*-----------------------------------------------------------------*/
8347 /* genNearPointerSet - pic14_emitcode for near pointer put                */
8348 /*-----------------------------------------------------------------*/
8349 static void genNearPointerSet (operand *right,
8350                                operand *result, 
8351                                iCode *ic)
8352 {
8353     asmop *aop = NULL;
8354     char *l;
8355     sym_link *retype;
8356     sym_link *ptype = operandType(result);
8357
8358     
8359     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8360     retype= getSpec(operandType(right));
8361
8362     aopOp(result,ic,FALSE);
8363     
8364     /* if the result is rematerializable &
8365        in data space & not a bit variable */
8366     //if (AOP_TYPE(result) == AOP_IMMD &&
8367     if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
8368         DCL_TYPE(ptype) == POINTER   &&
8369         !IS_BITVAR(retype)) {
8370         genDataPointerSet (right,result,ic);
8371         return;
8372     }
8373
8374     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8375
8376     /* if the value is already in a pointer register
8377     then don't need anything more */
8378     if (!AOP_INPREG(AOP(result))) {
8379         /* otherwise get a free pointer register */
8380         //aop = newAsmop(0);
8381         //preg = getFreePtr(ic,&aop,FALSE);
8382         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8383         //pic14_emitcode("mov","%s,%s",
8384         //         preg->name,
8385         //         aopGet(AOP(result),0,FALSE,TRUE));
8386         //rname = preg->name ;
8387         pic14_emitcode("movwf","fsr");
8388     }// else
8389     //   rname = aopGet(AOP(result),0,FALSE,FALSE);
8390
8391     freeAsmop(result,NULL,ic,TRUE);
8392     aopOp (right,ic,FALSE);
8393     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8394
8395     /* if bitfield then unpack the bits */
8396     if (IS_BITVAR(retype)) {
8397       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
8398              "The programmer is obviously confused");
8399       //genPackBits (retype,right,rname,POINTER);
8400       exit(1);
8401     }
8402     else {
8403         /* we have can just get the values */
8404         int size = AOP_SIZE(right);
8405         int offset = 0 ;    
8406
8407     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8408         while (size--) {
8409             l = aopGet(AOP(right),offset,FALSE,TRUE);
8410             if (*l == '@' ) {
8411               //MOVA(l);
8412               //pic14_emitcode("mov","@%s,a",rname);
8413               pic14_emitcode("movf","indf,w ;1");
8414             } else {
8415
8416               if (AOP_TYPE(right) == AOP_LIT) {
8417                 unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8418                 if(lit) {
8419                   pic14_emitcode("movlw","%s",l);
8420                   pic14_emitcode("movwf","indf ;2");
8421                 } else 
8422                   pic14_emitcode("clrf","indf");
8423               }else {
8424                 pic14_emitcode("movf","%s,w",l);
8425                 pic14_emitcode("movwf","indf ;2");
8426               }
8427             //pic14_emitcode("mov","@%s,%s",rname,l);
8428             }
8429             if (size)
8430               pic14_emitcode("incf","fsr,f ;3");
8431             //pic14_emitcode("inc","%s",rname);
8432             offset++;
8433         }
8434     }
8435
8436     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8437     /* now some housekeeping stuff */
8438     if (aop) {
8439         /* we had to allocate for this iCode */
8440         freeAsmop(NULL,aop,ic,TRUE);
8441     } else { 
8442         /* we did not allocate which means left
8443         already in a pointer register, then
8444         if size > 0 && this could be used again
8445         we have to point it back to where it 
8446         belongs */
8447     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8448         if (AOP_SIZE(right) > 1 &&
8449             !OP_SYMBOL(result)->remat &&
8450             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8451               ic->depth )) {
8452             int size = AOP_SIZE(right) - 1;
8453             while (size--)
8454               pic14_emitcode("decf","fsr,f");
8455               //pic14_emitcode("dec","%s",rname);
8456         }
8457     }
8458
8459     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8460     /* done */
8461     freeAsmop(right,NULL,ic,TRUE);
8462
8463
8464 }
8465
8466 /*-----------------------------------------------------------------*/
8467 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
8468 /*-----------------------------------------------------------------*/
8469 static void genPagedPointerSet (operand *right,
8470                                operand *result, 
8471                                iCode *ic)
8472 {
8473     asmop *aop = NULL;
8474     regs *preg = NULL ;
8475     char *rname , *l;
8476     sym_link *retype;
8477        
8478     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8479
8480     retype= getSpec(operandType(right));
8481     
8482     aopOp(result,ic,FALSE);
8483     
8484     /* if the value is already in a pointer register
8485        then don't need anything more */
8486     if (!AOP_INPREG(AOP(result))) {
8487         /* otherwise get a free pointer register */
8488         aop = newAsmop(0);
8489         preg = getFreePtr(ic,&aop,FALSE);
8490         pic14_emitcode("mov","%s,%s",
8491                 preg->name,
8492                 aopGet(AOP(result),0,FALSE,TRUE));
8493         rname = preg->name ;
8494     } else
8495         rname = aopGet(AOP(result),0,FALSE,FALSE);
8496     
8497     freeAsmop(result,NULL,ic,TRUE);
8498     aopOp (right,ic,FALSE);
8499
8500     /* if bitfield then unpack the bits */
8501     if (IS_BITVAR(retype)) 
8502         genPackBits (retype,right,rname,PPOINTER);
8503     else {
8504         /* we have can just get the values */
8505         int size = AOP_SIZE(right);
8506         int offset = 0 ;        
8507         
8508         while (size--) {
8509             l = aopGet(AOP(right),offset,FALSE,TRUE);
8510             
8511             MOVA(l);
8512             pic14_emitcode("movx","@%s,a",rname);
8513
8514             if (size)
8515                 pic14_emitcode("inc","%s",rname);
8516
8517             offset++;
8518         }
8519     }
8520     
8521     /* now some housekeeping stuff */
8522     if (aop) {
8523         /* we had to allocate for this iCode */
8524         freeAsmop(NULL,aop,ic,TRUE);
8525     } else { 
8526         /* we did not allocate which means left
8527            already in a pointer register, then
8528            if size > 0 && this could be used again
8529            we have to point it back to where it 
8530            belongs */
8531         if (AOP_SIZE(right) > 1 &&
8532             !OP_SYMBOL(result)->remat &&
8533             ( OP_SYMBOL(result)->liveTo > ic->seq ||
8534               ic->depth )) {
8535             int size = AOP_SIZE(right) - 1;
8536             while (size--)
8537                 pic14_emitcode("dec","%s",rname);
8538         }
8539     }
8540
8541     /* done */
8542     freeAsmop(right,NULL,ic,TRUE);
8543     
8544         
8545 }
8546
8547 /*-----------------------------------------------------------------*/
8548 /* genFarPointerSet - set value from far space                     */
8549 /*-----------------------------------------------------------------*/
8550 static void genFarPointerSet (operand *right,
8551                               operand *result, iCode *ic)
8552 {
8553     int size, offset ;
8554     sym_link *retype = getSpec(operandType(right));
8555
8556     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8557     aopOp(result,ic,FALSE);
8558
8559     /* if the operand is already in dptr 
8560     then we do nothing else we move the value to dptr */
8561     if (AOP_TYPE(result) != AOP_STR) {
8562         /* if this is remateriazable */
8563         if (AOP_TYPE(result) == AOP_IMMD)
8564             pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8565         else { /* we need to get it byte by byte */
8566             pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
8567             pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
8568             if (options.model == MODEL_FLAT24)
8569             {
8570                pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
8571             }
8572         }
8573     }
8574     /* so dptr know contains the address */
8575     freeAsmop(result,NULL,ic,TRUE);
8576     aopOp(right,ic,FALSE);
8577
8578     /* if bit then unpack */
8579     if (IS_BITVAR(retype)) 
8580         genPackBits(retype,right,"dptr",FPOINTER);
8581     else {
8582         size = AOP_SIZE(right);
8583         offset = 0 ;
8584
8585         while (size--) {
8586             char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8587             MOVA(l);
8588             pic14_emitcode("movx","@dptr,a");
8589             if (size)
8590                 pic14_emitcode("inc","dptr");
8591         }
8592     }
8593
8594     freeAsmop(right,NULL,ic,TRUE);
8595 }
8596
8597 /*-----------------------------------------------------------------*/
8598 /* genGenPointerSet - set value from generic pointer space         */
8599 /*-----------------------------------------------------------------*/
8600 static void genGenPointerSet (operand *right,
8601                               operand *result, iCode *ic)
8602 {
8603   int size, offset ;
8604   sym_link *retype = getSpec(operandType(right));
8605
8606   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8607
8608   aopOp(result,ic,FALSE);
8609   aopOp(right,ic,FALSE);
8610   size = AOP_SIZE(right);
8611
8612   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8613
8614   /* if the operand is already in dptr 
8615      then we do nothing else we move the value to dptr */
8616   if (AOP_TYPE(result) != AOP_STR) {
8617     /* if this is remateriazable */
8618     if (AOP_TYPE(result) == AOP_IMMD) {
8619       pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
8620       pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
8621     }
8622     else { /* we need to get it byte by byte */
8623       //char *l = aopGet(AOP(result),0,FALSE,FALSE);
8624       size = AOP_SIZE(right);
8625       offset = 0 ;
8626
8627       /* hack hack! see if this the FSR. If so don't load W */
8628       if(AOP_TYPE(right) != AOP_ACC) {
8629
8630         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8631         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8632
8633         //if(size==2)
8634         //emitpcode(POC_DECF,popCopyReg(&pc_fsr));
8635         //if(size==4) {
8636         //  emitpcode(POC_MOVLW,popGetLit(0xfd));
8637         //  emitpcode(POC_ADDWF,popCopyReg(&pc_fsr));
8638         //}
8639
8640         while(size--) {
8641           emitpcode(POC_MOVFW,popGet(AOP(right),offset++));
8642           emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8643           
8644           if(size)
8645             emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8646         }
8647
8648
8649         goto release;
8650       } 
8651
8652       if(aopIdx(AOP(result),0) != 4) {
8653
8654         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8655         goto release;
8656       }
8657
8658       emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8659       goto release;
8660
8661     }
8662   }
8663   /* so dptr know contains the address */
8664
8665
8666   /* if bit then unpack */
8667   if (IS_BITVAR(retype)) 
8668     genPackBits(retype,right,"dptr",GPOINTER);
8669   else {
8670     size = AOP_SIZE(right);
8671     offset = 0 ;
8672
8673     while (--size) {
8674       //char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
8675       if(size)
8676         pic14_emitcode("incf","fsr,f");
8677       pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset++,FALSE,FALSE));
8678       pic14_emitcode("movwf","indf");
8679       //MOVA(l);
8680       //DEBUGpic14_emitcode(";lcall","__gptrput");
8681       //if (size)
8682       //    pic14_emitcode("inc","dptr");
8683     }
8684   }
8685
8686  release:
8687   freeAsmop(right,NULL,ic,TRUE);
8688   freeAsmop(result,NULL,ic,TRUE);
8689 }
8690
8691 /*-----------------------------------------------------------------*/
8692 /* genPointerSet - stores the value into a pointer location        */
8693 /*-----------------------------------------------------------------*/
8694 static void genPointerSet (iCode *ic)
8695 {    
8696     operand *right, *result ;
8697     sym_link *type, *etype;
8698     int p_type;
8699
8700     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8701
8702     right = IC_RIGHT(ic);
8703     result = IC_RESULT(ic) ;
8704
8705     /* depending on the type of pointer we need to
8706     move it to the correct pointer register */
8707     type = operandType(result);
8708     etype = getSpec(type);
8709     /* if left is of type of pointer then it is simple */
8710     if (IS_PTR(type) && !IS_FUNC(type->next)) {
8711         p_type = DCL_TYPE(type);
8712     }
8713     else {
8714         /* we have to go by the storage class */
8715         p_type = PTR_TYPE(SPEC_OCLS(etype));
8716
8717 /*      if (SPEC_OCLS(etype)->codesp ) { */
8718 /*          p_type = CPOINTER ;  */
8719 /*      } */
8720 /*      else */
8721 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
8722 /*              p_type = FPOINTER ; */
8723 /*          else */
8724 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
8725 /*                  p_type = PPOINTER ; */
8726 /*              else */
8727 /*                  if (SPEC_OCLS(etype) == idata ) */
8728 /*                      p_type = IPOINTER ; */
8729 /*                  else */
8730 /*                      p_type = POINTER ; */
8731     }
8732
8733     /* now that we have the pointer type we assign
8734     the pointer values */
8735     switch (p_type) {
8736
8737     case POINTER:
8738     case IPOINTER:
8739         genNearPointerSet (right,result,ic);
8740         break;
8741
8742     case PPOINTER:
8743         genPagedPointerSet (right,result,ic);
8744         break;
8745
8746     case FPOINTER:
8747         genFarPointerSet (right,result,ic);
8748         break;
8749
8750     case GPOINTER:
8751         genGenPointerSet (right,result,ic);
8752         break;
8753
8754     default:
8755       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
8756               "genPointerSet: illegal pointer type");
8757     }
8758 }
8759
8760 /*-----------------------------------------------------------------*/
8761 /* genIfx - generate code for Ifx statement                        */
8762 /*-----------------------------------------------------------------*/
8763 static void genIfx (iCode *ic, iCode *popIc)
8764 {
8765   operand *cond = IC_COND(ic);
8766   int isbit =0;
8767
8768   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8769
8770   aopOp(cond,ic,FALSE);
8771
8772   /* get the value into acc */
8773   if (AOP_TYPE(cond) != AOP_CRY)
8774     pic14_toBoolean(cond);
8775   else
8776     isbit = 1;
8777   /* the result is now in the accumulator */
8778   freeAsmop(cond,NULL,ic,TRUE);
8779
8780   /* if there was something to be popped then do it */
8781   if (popIc)
8782     genIpop(popIc);
8783
8784   /* if the condition is  a bit variable */
8785   if (isbit && IS_ITEMP(cond) && 
8786       SPIL_LOC(cond)) {
8787     genIfxJump(ic,SPIL_LOC(cond)->rname);
8788     DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
8789   }
8790   else {
8791     if (isbit && !IS_ITEMP(cond))
8792       genIfxJump(ic,OP_SYMBOL(cond)->rname);
8793     else
8794       genIfxJump(ic,"a");
8795   }
8796   ic->generated = 1;
8797
8798 }
8799
8800 /*-----------------------------------------------------------------*/
8801 /* genAddrOf - generates code for address of                       */
8802 /*-----------------------------------------------------------------*/
8803 static void genAddrOf (iCode *ic)
8804 {
8805   operand *right, *result, *left;
8806   int size, offset ;
8807
8808   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8809
8810
8811   //aopOp(IC_RESULT(ic),ic,FALSE);
8812
8813   aopOp((left=IC_LEFT(ic)),ic,FALSE);
8814   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
8815   aopOp((result=IC_RESULT(ic)),ic,TRUE);
8816
8817   DEBUGpic14_AopType(__LINE__,left,right,result);
8818
8819   size = AOP_SIZE(IC_RESULT(ic));
8820   offset = 0;
8821
8822   while (size--) {
8823     emitpcode(POC_MOVLW, popGet(AOP(left),offset));
8824     emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8825     offset++;
8826   }
8827
8828   freeAsmop(left,NULL,ic,FALSE);
8829   freeAsmop(result,NULL,ic,TRUE);
8830
8831 }
8832
8833 #if 0
8834 /*-----------------------------------------------------------------*/
8835 /* genFarFarAssign - assignment when both are in far space         */
8836 /*-----------------------------------------------------------------*/
8837 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
8838 {
8839     int size = AOP_SIZE(right);
8840     int offset = 0;
8841     char *l ;
8842     /* first push the right side on to the stack */
8843     while (size--) {
8844         l = aopGet(AOP(right),offset++,FALSE,FALSE);
8845         MOVA(l);
8846         pic14_emitcode ("push","acc");
8847     }
8848     
8849     freeAsmop(right,NULL,ic,FALSE);
8850     /* now assign DPTR to result */
8851     aopOp(result,ic,FALSE);
8852     size = AOP_SIZE(result);
8853     while (size--) {
8854         pic14_emitcode ("pop","acc");
8855         aopPut(AOP(result),"a",--offset);
8856     }
8857     freeAsmop(result,NULL,ic,FALSE);
8858         
8859 }
8860 #endif
8861
8862 /*-----------------------------------------------------------------*/
8863 /* genAssign - generate code for assignment                        */
8864 /*-----------------------------------------------------------------*/
8865 static void genAssign (iCode *ic)
8866 {
8867   operand *result, *right;
8868   int size, offset,know_W;
8869   unsigned long lit = 0L;
8870
8871   result = IC_RESULT(ic);
8872   right  = IC_RIGHT(ic) ;
8873
8874   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8875
8876   /* if they are the same */
8877   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
8878     return ;
8879
8880   aopOp(right,ic,FALSE);
8881   aopOp(result,ic,TRUE);
8882
8883   DEBUGpic14_AopType(__LINE__,NULL,right,result);
8884
8885   /* if they are the same registers */
8886   if (pic14_sameRegs(AOP(right),AOP(result)))
8887     goto release;
8888
8889   /* if the result is a bit */
8890   if (AOP_TYPE(result) == AOP_CRY) {
8891
8892     /* if the right size is a literal then
8893        we know what the value is */
8894     if (AOP_TYPE(right) == AOP_LIT) {
8895           
8896       emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
8897                   popGet(AOP(result),0));
8898
8899       if (((int) operandLitValue(right))) 
8900         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8901                        AOP(result)->aopu.aop_dir,
8902                        AOP(result)->aopu.aop_dir);
8903       else
8904         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8905                        AOP(result)->aopu.aop_dir,
8906                        AOP(result)->aopu.aop_dir);
8907       goto release;
8908     }
8909
8910     /* the right is also a bit variable */
8911     if (AOP_TYPE(right) == AOP_CRY) {
8912       emitpcode(POC_BCF,    popGet(AOP(result),0));
8913       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
8914       emitpcode(POC_BSF,    popGet(AOP(result),0));
8915
8916       pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
8917                      AOP(result)->aopu.aop_dir,
8918                      AOP(result)->aopu.aop_dir);
8919       pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
8920                      AOP(right)->aopu.aop_dir,
8921                      AOP(right)->aopu.aop_dir);
8922       pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
8923                      AOP(result)->aopu.aop_dir,
8924                      AOP(result)->aopu.aop_dir);
8925       goto release ;
8926     }
8927
8928     /* we need to or */
8929     emitpcode(POC_BCF,    popGet(AOP(result),0));
8930     pic14_toBoolean(right);
8931     emitSKPZ;
8932     emitpcode(POC_BSF,    popGet(AOP(result),0));
8933     //aopPut(AOP(result),"a",0);
8934     goto release ;
8935   }
8936
8937   /* bit variables done */
8938   /* general case */
8939   size = AOP_SIZE(result);
8940   offset = 0 ;
8941   if(AOP_TYPE(right) == AOP_LIT)
8942     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
8943
8944   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
8945   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8946     if(aopIdx(AOP(result),0) == 4) {
8947   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8948       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8949       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8950       goto release;
8951     } else
8952       DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
8953   }
8954
8955   know_W=-1;
8956   while (size--) {
8957   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8958     if(AOP_TYPE(right) == AOP_LIT) {
8959       if(lit&0xff) {
8960         if(know_W != (lit&0xff))
8961           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
8962         know_W = lit&0xff;
8963         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8964       } else
8965         emitpcode(POC_CLRF, popGet(AOP(result),offset));
8966
8967       lit >>= 8;
8968
8969     } else if (AOP_TYPE(right) == AOP_CRY) {
8970       emitpcode(POC_CLRF, popGet(AOP(result),offset));
8971       if(offset == 0) {
8972         emitpcode(POC_BTFSS, popGet(AOP(right),0));
8973         emitpcode(POC_INCF, popGet(AOP(result),0));
8974       }
8975     } else {
8976   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8977       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
8978       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8979     }
8980             
8981     offset++;
8982   }
8983
8984     
8985  release:
8986   freeAsmop (right,NULL,ic,FALSE);
8987   freeAsmop (result,NULL,ic,TRUE);
8988 }   
8989
8990 /*-----------------------------------------------------------------*/
8991 /* genJumpTab - genrates code for jump table                       */
8992 /*-----------------------------------------------------------------*/
8993 static void genJumpTab (iCode *ic)
8994 {
8995     symbol *jtab;
8996     char *l;
8997
8998     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8999
9000     aopOp(IC_JTCOND(ic),ic,FALSE);
9001     /* get the condition into accumulator */
9002     l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9003     MOVA(l);
9004     /* multiply by three */
9005     pic14_emitcode("add","a,acc");
9006     pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9007
9008     jtab = newiTempLabel(NULL);
9009     pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9010     pic14_emitcode("jmp","@a+dptr");
9011     pic14_emitcode("","%05d_DS_:",jtab->key+100);
9012
9013     emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9014     emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9015     emitSKPNC;
9016     emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9017     emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9018     emitpLabel(jtab->key);
9019
9020     freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9021
9022     /* now generate the jump labels */
9023     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9024          jtab = setNextItem(IC_JTLABELS(ic))) {
9025         pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9026         emitpcode(POC_GOTO,popGetLabel(jtab->key));
9027         
9028     }
9029
9030 }
9031
9032 /*-----------------------------------------------------------------*/
9033 /* genMixedOperation - gen code for operators between mixed types  */
9034 /*-----------------------------------------------------------------*/
9035 /*
9036   TSD - Written for the PIC port - but this unfortunately is buggy.
9037   This routine is good in that it is able to efficiently promote 
9038   types to different (larger) sizes. Unfortunately, the temporary
9039   variables that are optimized out by this routine are sometimes
9040   used in other places. So until I know how to really parse the 
9041   iCode tree, I'm going to not be using this routine :(.
9042 */
9043 static int genMixedOperation (iCode *ic)
9044 {
9045 #if 0
9046   operand *result = IC_RESULT(ic);
9047   sym_link *ctype = operandType(IC_LEFT(ic));
9048   operand *right = IC_RIGHT(ic);
9049   int ret = 0;
9050   int big,small;
9051   int offset;
9052
9053   iCode *nextic;
9054   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9055
9056   pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9057
9058   nextic = ic->next;
9059   if(!nextic)
9060     return 0;
9061
9062   nextright = IC_RIGHT(nextic);
9063   nextleft  = IC_LEFT(nextic);
9064   nextresult = IC_RESULT(nextic);
9065
9066   aopOp(right,ic,FALSE);
9067   aopOp(result,ic,FALSE);
9068   aopOp(nextright,  nextic, FALSE);
9069   aopOp(nextleft,   nextic, FALSE);
9070   aopOp(nextresult, nextic, FALSE);
9071
9072   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9073
9074     operand *t = right;
9075     right = nextright;
9076     nextright = t; 
9077
9078     pic14_emitcode(";remove right +","");
9079
9080   } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9081 /*
9082     operand *t = right;
9083     right = nextleft;
9084     nextleft = t; 
9085 */
9086     pic14_emitcode(";remove left +","");
9087   } else
9088     return 0;
9089
9090   big = AOP_SIZE(nextleft);
9091   small = AOP_SIZE(nextright);
9092
9093   switch(nextic->op) {
9094
9095   case '+':
9096     pic14_emitcode(";optimize a +","");
9097     /* if unsigned or not an integral type */
9098     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9099       pic14_emitcode(";add a bit to something","");
9100     } else {
9101
9102       pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9103
9104       if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9105         pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9106         pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9107       } else
9108         pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9109
9110       offset = 0;
9111       while(--big) {
9112
9113         offset++;
9114
9115         if(--small) {
9116           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9117             pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9118             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9119           }
9120
9121           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9122           emitSKPNC;
9123           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9124                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9125                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9126           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9127           pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9128
9129         } else {
9130           pic14_emitcode("rlf","known_zero,w");
9131
9132           /*
9133             if right is signed
9134               btfsc  right,7
9135                addlw ff
9136           */
9137           if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9138             pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9139             pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9140           } else {
9141             pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9142           }
9143         }
9144       }
9145       ret = 1;
9146     }
9147   }
9148   ret = 1;
9149
9150 release:
9151   freeAsmop(right,NULL,ic,TRUE);
9152   freeAsmop(result,NULL,ic,TRUE);
9153   freeAsmop(nextright,NULL,ic,TRUE);
9154   freeAsmop(nextleft,NULL,ic,TRUE);
9155   if(ret)
9156     nextic->generated = 1;
9157
9158   return ret;
9159 #else
9160   return 0;
9161 #endif
9162 }
9163 /*-----------------------------------------------------------------*/
9164 /* genCast - gen code for casting                                  */
9165 /*-----------------------------------------------------------------*/
9166 static void genCast (iCode *ic)
9167 {
9168     operand *result = IC_RESULT(ic);
9169     sym_link *ctype = operandType(IC_LEFT(ic));
9170     sym_link *rtype = operandType(IC_RIGHT(ic));
9171     operand *right = IC_RIGHT(ic);
9172     int size, offset ;
9173
9174     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9175     /* if they are equivalent then do nothing */
9176     if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9177         return ;
9178
9179     aopOp(right,ic,FALSE) ;
9180     aopOp(result,ic,FALSE);
9181
9182     DEBUGpic14_AopType(__LINE__,NULL,right,result);
9183
9184     /* if the result is a bit */
9185     if (AOP_TYPE(result) == AOP_CRY) {
9186         /* if the right size is a literal then
9187         we know what the value is */
9188       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9189         if (AOP_TYPE(right) == AOP_LIT) {
9190
9191           emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9192                       popGet(AOP(result),0));
9193
9194             if (((int) operandLitValue(right))) 
9195               pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
9196                        AOP(result)->aopu.aop_dir,
9197                        AOP(result)->aopu.aop_dir);
9198             else
9199               pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
9200                        AOP(result)->aopu.aop_dir,
9201                        AOP(result)->aopu.aop_dir);
9202
9203             goto release;
9204         }
9205
9206         /* the right is also a bit variable */
9207         if (AOP_TYPE(right) == AOP_CRY) {
9208
9209           emitCLRC;
9210           emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9211
9212           pic14_emitcode("clrc","");
9213           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9214                    AOP(right)->aopu.aop_dir,
9215                    AOP(right)->aopu.aop_dir);
9216             aopPut(AOP(result),"c",0);
9217             goto release ;
9218         }
9219
9220         /* we need to or */
9221         if (AOP_TYPE(right) == AOP_REG) {
9222           emitpcode(POC_BCF,    popGet(AOP(result),0));
9223           emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
9224           emitpcode(POC_BSF,    popGet(AOP(result),0));
9225         }
9226         pic14_toBoolean(right);
9227         aopPut(AOP(result),"a",0);
9228         goto release ;
9229     }
9230
9231     if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
9232       int offset = 1;
9233       size = AOP_SIZE(result);
9234
9235       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9236
9237       emitpcode(POC_CLRF,   popGet(AOP(result),0));
9238       emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9239       emitpcode(POC_INCF,   popGet(AOP(result),0));
9240
9241       while (size--)
9242         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9243
9244       goto release;
9245     }
9246
9247     /* if they are the same size : or less */
9248     if (AOP_SIZE(result) <= AOP_SIZE(right)) {
9249
9250         /* if they are in the same place */
9251       if (pic14_sameRegs(AOP(right),AOP(result)))
9252         goto release;
9253
9254       DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9255       if (IS_PTR_CONST(rtype))
9256         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
9257       if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
9258         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
9259
9260       if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
9261         emitpcode(POC_MOVLW, popGet(AOP(right),0));
9262         emitpcode(POC_MOVWF, popGet(AOP(result),0));
9263         emitpcode(POC_MOVLW, popGet(AOP(right),1));
9264         emitpcode(POC_MOVWF, popGet(AOP(result),1));
9265         if(AOP_SIZE(result) <2)
9266           fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
9267
9268       } else {
9269
9270         /* if they in different places then copy */
9271         size = AOP_SIZE(result);
9272         offset = 0 ;
9273         while (size--) {
9274           emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9275           emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9276
9277           //aopPut(AOP(result),
9278           // aopGet(AOP(right),offset,FALSE,FALSE),
9279           // offset);
9280
9281           offset++;
9282         }
9283       }
9284       goto release;
9285     }
9286
9287
9288     /* if the result is of type pointer */
9289     if (IS_PTR(ctype)) {
9290
9291         int p_type;
9292         sym_link *type = operandType(right);
9293         sym_link *etype = getSpec(type);
9294       DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
9295
9296         /* pointer to generic pointer */
9297         if (IS_GENPTR(ctype)) {
9298             char *l = zero;
9299             
9300             if (IS_PTR(type)) 
9301                 p_type = DCL_TYPE(type);
9302             else {
9303                 /* we have to go by the storage class */
9304                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9305
9306 /*              if (SPEC_OCLS(etype)->codesp )  */
9307 /*                  p_type = CPOINTER ;  */
9308 /*              else */
9309 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9310 /*                      p_type = FPOINTER ; */
9311 /*                  else */
9312 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9313 /*                          p_type = PPOINTER; */
9314 /*                      else */
9315 /*                          if (SPEC_OCLS(etype) == idata ) */
9316 /*                              p_type = IPOINTER ; */
9317 /*                          else */
9318 /*                              p_type = POINTER ; */
9319             }
9320                 
9321             /* the first two bytes are known */
9322             size = GPTRSIZE - 1; 
9323             offset = 0 ;
9324             while (size--) {
9325               if(offset < AOP_SIZE(right))
9326                 aopPut(AOP(result),
9327                        aopGet(AOP(right),offset,FALSE,FALSE),
9328                        offset);
9329               else
9330                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
9331               offset++;
9332             }
9333             /* the last byte depending on type */
9334             switch (p_type) {
9335             case IPOINTER:
9336             case POINTER:
9337                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
9338                 break;
9339             case FPOINTER:
9340               pic14_emitcode(";BUG!? ","%d",__LINE__);
9341                 l = one;
9342                 break;
9343             case CPOINTER:
9344               pic14_emitcode(";BUG!? ","%d",__LINE__);
9345                 l = "#0x02";
9346                 break;                          
9347             case PPOINTER:
9348               pic14_emitcode(";BUG!? ","%d",__LINE__);
9349                 l = "#0x03";
9350                 break;
9351                 
9352             default:
9353                 /* this should never happen */
9354                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9355                        "got unknown pointer type");
9356                 exit(1);
9357             }
9358             //aopPut(AOP(result),l, GPTRSIZE - 1);          
9359             goto release ;
9360         }
9361         
9362         /* just copy the pointers */
9363         size = AOP_SIZE(result);
9364         offset = 0 ;
9365         while (size--) {
9366             aopPut(AOP(result),
9367                    aopGet(AOP(right),offset,FALSE,FALSE),
9368                    offset);
9369             offset++;
9370         }
9371         goto release ;
9372     }
9373     
9374
9375
9376     /* so we now know that the size of destination is greater
9377     than the size of the source.
9378     Now, if the next iCode is an operator then we might be
9379     able to optimize the operation without performing a cast.
9380     */
9381     if(genMixedOperation(ic))
9382       goto release;
9383
9384     DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9385     
9386     /* we move to result for the size of source */
9387     size = AOP_SIZE(right);
9388     offset = 0 ;
9389     while (size--) {
9390       emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
9391       emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
9392       offset++;
9393     }
9394
9395     /* now depending on the sign of the destination */
9396     size = AOP_SIZE(result) - AOP_SIZE(right);
9397     /* if unsigned or not an integral type */
9398     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
9399       while (size--)
9400         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
9401     } else {
9402       /* we need to extend the sign :{ */
9403
9404       if(size == 1) {
9405         /* Save one instruction of casting char to int */
9406         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
9407         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9408         emitpcode(POC_DECF,   popGet(AOP(result),offset));
9409       } else {
9410         emitpcodeNULLop(POC_CLRW);
9411
9412         if(offset)
9413           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
9414         else
9415           emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
9416         
9417         emitpcode(POC_MOVLW,   popGetLit(0xff));
9418
9419         while (size--)
9420           emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
9421       }
9422     }
9423
9424 release:
9425     freeAsmop(right,NULL,ic,TRUE);
9426     freeAsmop(result,NULL,ic,TRUE);
9427
9428 }
9429
9430 /*-----------------------------------------------------------------*/
9431 /* genDjnz - generate decrement & jump if not zero instrucion      */
9432 /*-----------------------------------------------------------------*/
9433 static int genDjnz (iCode *ic, iCode *ifx)
9434 {
9435     symbol *lbl, *lbl1;
9436     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9437
9438     if (!ifx)
9439         return 0;
9440     
9441     /* if the if condition has a false label
9442        then we cannot save */
9443     if (IC_FALSE(ifx))
9444         return 0;
9445
9446     /* if the minus is not of the form 
9447        a = a - 1 */
9448     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
9449         !IS_OP_LITERAL(IC_RIGHT(ic)))
9450         return 0;
9451
9452     if (operandLitValue(IC_RIGHT(ic)) != 1)
9453         return 0;
9454
9455     /* if the size of this greater than one then no
9456        saving */
9457     if (getSize(operandType(IC_RESULT(ic))) > 1)
9458         return 0;
9459
9460     /* otherwise we can save BIG */
9461     lbl = newiTempLabel(NULL);
9462     lbl1= newiTempLabel(NULL);
9463
9464     aopOp(IC_RESULT(ic),ic,FALSE);
9465     
9466     if (IS_AOP_PREG(IC_RESULT(ic))) {
9467         pic14_emitcode("dec","%s",
9468                  aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9469         pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9470         pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
9471     } else {    
9472
9473
9474       emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
9475       emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
9476
9477       pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
9478       pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
9479
9480     }
9481 /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
9482 /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
9483 /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
9484 /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
9485
9486     
9487     freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9488     ifx->generated = 1;
9489     return 1;
9490 }
9491
9492 /*-----------------------------------------------------------------*/
9493 /* genReceive - generate code for a receive iCode                  */
9494 /*-----------------------------------------------------------------*/
9495 static void genReceive (iCode *ic)
9496 {    
9497   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9498
9499   if (isOperandInFarSpace(IC_RESULT(ic)) && 
9500       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
9501         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
9502
9503     int size = getSize(operandType(IC_RESULT(ic)));
9504     int offset =  fReturnSizePic - size;
9505     while (size--) {
9506       pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
9507                                     fReturn[fReturnSizePic - offset - 1] : "acc"));
9508       offset++;
9509     }
9510     aopOp(IC_RESULT(ic),ic,FALSE);  
9511     size = AOP_SIZE(IC_RESULT(ic));
9512     offset = 0;
9513     while (size--) {
9514       pic14_emitcode ("pop","acc");
9515       aopPut (AOP(IC_RESULT(ic)),"a",offset++);
9516     }
9517         
9518   } else {
9519     _G.accInUse++;
9520     aopOp(IC_RESULT(ic),ic,FALSE);  
9521     _G.accInUse--;
9522     assignResultValue(IC_RESULT(ic));   
9523   }
9524
9525   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
9526 }
9527
9528 /*-----------------------------------------------------------------*/
9529 /* genpic14Code - generate code for pic14 based controllers        */
9530 /*-----------------------------------------------------------------*/
9531 /*
9532  * At this point, ralloc.c has gone through the iCode and attempted
9533  * to optimize in a way suitable for a PIC. Now we've got to generate
9534  * PIC instructions that correspond to the iCode.
9535  *
9536  * Once the instructions are generated, we'll pass through both the
9537  * peep hole optimizer and the pCode optimizer.
9538  *-----------------------------------------------------------------*/
9539
9540 void genpic14Code (iCode *lic)
9541 {
9542     iCode *ic;
9543     int cln = 0;
9544
9545     lineHead = lineCurr = NULL;
9546
9547     pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
9548     addpBlock(pb);
9549
9550     /* if debug information required */
9551     if (options.debug && currFunc) { 
9552       if (currFunc) {
9553         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
9554         _G.debugLine = 1;
9555         if (IS_STATIC(currFunc->etype)) {
9556           pic14_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
9557           //addpCode2pBlock(pb,newpCodeLabel(moduleName,currFunc->name));
9558         } else {
9559           pic14_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
9560           //addpCode2pBlock(pb,newpCodeLabel(NULL,currFunc->name));
9561         }
9562         _G.debugLine = 0;
9563       }
9564     }
9565
9566
9567     for (ic = lic ; ic ; ic = ic->next ) {
9568
9569       DEBUGpic14_emitcode(";ic","");
9570         if ( cln != ic->lineno ) {
9571             if ( options.debug ) {
9572                 _G.debugLine = 1;
9573                 pic14_emitcode("",";C$%s$%d$%d$%d ==.",
9574                          FileBaseName(ic->filename),ic->lineno,
9575                          ic->level,ic->block);
9576                 _G.debugLine = 0;
9577             }
9578             pic14_emitcode("#CSRC","%s %d",FileBaseName(ic->filename),ic->lineno);
9579             pic14_emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno, 
9580                             printCLine(ic->filename, ic->lineno));
9581
9582             cln = ic->lineno ;
9583         }
9584         /* if the result is marked as
9585            spilt and rematerializable or code for
9586            this has already been generated then
9587            do nothing */
9588         if (resultRemat(ic) || ic->generated ) 
9589             continue ;
9590         
9591         /* depending on the operation */
9592         switch (ic->op) {
9593         case '!' :
9594             genNot(ic);
9595             break;
9596             
9597         case '~' :
9598             genCpl(ic);
9599             break;
9600             
9601         case UNARYMINUS:
9602             genUminus (ic);
9603             break;
9604             
9605         case IPUSH:
9606             genIpush (ic);
9607             break;
9608             
9609         case IPOP:
9610             /* IPOP happens only when trying to restore a 
9611                spilt live range, if there is an ifx statement
9612                following this pop then the if statement might
9613                be using some of the registers being popped which
9614                would destory the contents of the register so
9615                we need to check for this condition and handle it */
9616             if (ic->next            && 
9617                 ic->next->op == IFX &&
9618                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
9619                 genIfx (ic->next,ic);
9620             else
9621                 genIpop (ic);
9622             break; 
9623             
9624         case CALL:
9625             genCall (ic);
9626             break;
9627             
9628         case PCALL:
9629             genPcall (ic);
9630             break;
9631             
9632         case FUNCTION:
9633             genFunction (ic);
9634             break;
9635             
9636         case ENDFUNCTION:
9637             genEndFunction (ic);
9638             break;
9639             
9640         case RETURN:
9641             genRet (ic);
9642             break;
9643             
9644         case LABEL:
9645             genLabel (ic);
9646             break;
9647             
9648         case GOTO:
9649             genGoto (ic);
9650             break;
9651             
9652         case '+' :
9653             genPlus (ic) ;
9654             break;
9655             
9656         case '-' :
9657             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
9658                 genMinus (ic);
9659             break;
9660             
9661         case '*' :
9662             genMult (ic);
9663             break;
9664             
9665         case '/' :
9666             genDiv (ic) ;
9667             break;
9668             
9669         case '%' :
9670             genMod (ic);
9671             break;
9672             
9673         case '>' :
9674             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
9675             break;
9676             
9677         case '<' :
9678             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
9679             break;
9680             
9681         case LE_OP:
9682         case GE_OP:
9683         case NE_OP:
9684             
9685             /* note these two are xlated by algebraic equivalence
9686                during parsing SDCC.y */
9687             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9688                    "got '>=' or '<=' shouldn't have come here");
9689             break;      
9690             
9691         case EQ_OP:
9692             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
9693             break;          
9694             
9695         case AND_OP:
9696             genAndOp (ic);
9697             break;
9698             
9699         case OR_OP:
9700             genOrOp (ic);
9701             break;
9702             
9703         case '^' :
9704             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
9705             break;
9706             
9707         case '|' :
9708                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
9709             break;
9710             
9711         case BITWISEAND:
9712             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
9713             break;
9714             
9715         case INLINEASM:
9716             genInline (ic);
9717             break;
9718             
9719         case RRC:
9720             genRRC (ic);
9721             break;
9722             
9723         case RLC:
9724             genRLC (ic);
9725             break;
9726             
9727         case GETHBIT:
9728             genGetHbit (ic);
9729             break;
9730             
9731         case LEFT_OP:
9732             genLeftShift (ic);
9733             break;
9734             
9735         case RIGHT_OP:
9736             genRightShift (ic);
9737             break;
9738             
9739         case GET_VALUE_AT_ADDRESS:
9740             genPointerGet(ic);
9741             break;
9742             
9743         case '=' :
9744             if (POINTER_SET(ic))
9745                 genPointerSet(ic);
9746             else
9747                 genAssign(ic);
9748             break;
9749             
9750         case IFX:
9751             genIfx (ic,NULL);
9752             break;
9753             
9754         case ADDRESS_OF:
9755             genAddrOf (ic);
9756             break;
9757             
9758         case JUMPTABLE:
9759             genJumpTab (ic);
9760             break;
9761             
9762         case CAST:
9763             genCast (ic);
9764             break;
9765             
9766         case RECEIVE:
9767             genReceive(ic);
9768             break;
9769             
9770         case SEND:
9771             addSet(&_G.sendSet,ic);
9772             break;
9773
9774         default :
9775             ic = ic;
9776         }
9777     }
9778     
9779
9780     /* now we are ready to call the 
9781        peep hole optimizer */
9782     if (!options.nopeep) {
9783       peepHole (&lineHead);
9784     }
9785     /* now do the actual printing */
9786     printLine (lineHead,codeOutFile);
9787
9788 #ifdef PCODE_DEBUG
9789     DFPRINTF((stderr,"printing pBlock\n\n"));
9790     printpBlock(stdout,pb);
9791 #endif
9792
9793     return;
9794 }