* src/pic/gen.c (popGet): changed assert to allow for
[fw/sdcc] / src / pic / gen.c
1 /*-------------------------------------------------------------------------
2   gen.c - source file for code generation for pic
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 #include "common.h"
40 #include "SDCCpeeph.h"
41 #include "ralloc.h"
42 #include "pcode.h"
43 #include "gen.h"
44
45 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
46 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
47 void genMult8X8_8 (operand *, operand *,operand *);
48 extern void printpBlock(FILE *of, pBlock *pb);
49
50 static int labelOffset=0;
51 extern int debug_verbose;
52 static int optimized_for_speed = 0;
53
54 /* max_key keeps track of the largest label number used in 
55 a function. This is then used to adjust the label offset
56 for the next function.
57 */
58 static int max_key=0;
59 static int GpsuedoStkPtr=0;
60
61 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
62 unsigned int pic14aopLiteral (value *val, int offset);
63 const char *AopType(short type);
64
65 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
66
67 /* this is the down and dirty file with all kinds of 
68 kludgy & hacky stuff. This is what it is all about
69 CODE GENERATION for a specific MCU . some of the
70 routines may be reusable, will have to see */
71
72 static char *zero = "#0x00";
73 static char *one  = "#0x01";
74 static char *spname = "sp";
75
76 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
77 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
78 static char **fReturn = fReturnpic14;
79
80 static char *accUse[] = {"a","b"};
81
82 //static short rbank = -1;
83
84 static struct {
85         short r0Pushed;
86         short r1Pushed;
87         short accInUse;
88         short inLine;
89         short debugLine;
90         short nRegsSaved;
91         set *sendSet;
92 } _G;
93
94 /* Resolved ifx structure. This structure stores information
95 about an iCode ifx that makes it easier to generate code.
96 */
97 typedef struct resolvedIfx {
98         symbol *lbl;     /* pointer to a label */
99         int condition;   /* true or false ifx */
100         int generated;   /* set true when the code associated with the ifx
101                           * is generated */
102 } resolvedIfx;
103
104 extern int pic14_ptrRegReq ;
105 extern int pic14_nRegs;
106 extern FILE *codeOutFile;
107 static void saverbank (int, iCode *,bool);
108
109 static lineNode *lineHead = NULL;
110 static lineNode *lineCurr = NULL;
111
112 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
115 0x07, 0x03, 0x01, 0x00};
116
117 static  pBlock *pb;
118
119 /*-----------------------------------------------------------------*/
120 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
121 /*                                 exponent of 2 is returned, otherwise -1 is      */
122 /*                                 returned.                                                                       */
123 /* note that this is similar to the function `powof2' in SDCCsymt  */
124 /* if(n == 2^y)                                                                                                    */
125 /*       return y;                                                                                                         */
126 /* return -1;                                                                                                      */
127 /*-----------------------------------------------------------------*/
128 static int my_powof2 (unsigned long num)
129 {
130         if(num) {
131                 if( (num & (num-1)) == 0) {
132                         int nshifts = -1;
133                         while(num) {
134                                 num>>=1;
135                                 nshifts++;
136                         }
137                         return nshifts;
138                 }
139         }
140         
141         return -1;
142 }
143
144 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
145 {
146         
147         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
148                 line_no,
149                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
150                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
151                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
152                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
153                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
154                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
155                 ((result) ? AOP_SIZE(result) : 0));
156         
157 }
158
159 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
160 {
161         
162         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
163                 line_no,
164                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
165                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
166                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
167                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
168                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
169                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
170         
171 }
172
173 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
174 {
175         va_list ap;
176         char lb[INITIAL_INLINEASM];  
177         char *lbp = lb;
178         
179         if(!debug_verbose && !options.debug)
180                 return;
181         
182         va_start(ap,fmt);   
183         
184         if (inst && *inst) {
185                 if (fmt && *fmt)
186                         sprintf(lb,"%s\t",inst);
187                 else
188                         sprintf(lb,"%s",inst);
189                 vsprintf(lb+(strlen(lb)),fmt,ap);
190         }  else
191                 vsprintf(lb,fmt,ap);
192         
193         while (isspace(*lbp)) lbp++;
194         
195         if (lbp && *lbp) 
196                 lineCurr = (lineCurr ?
197                 connectLine(lineCurr,newLineNode(lb)) :
198         (lineHead = newLineNode(lb)));
199         lineCurr->isInline = _G.inLine;
200         lineCurr->isDebug  = _G.debugLine;
201         
202         addpCode2pBlock(pb,newpCodeCharP(lb));
203         
204         va_end(ap);
205 }
206
207 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
208 {
209 #if defined (HAVE_VSNPRINTF)
210   vsnprintf (buf, size, fmt, ap);
211 #elif defined (HAVE_VSPRINTF)
212   vsprintf (buf, size, fmt, ap);
213   if (strlen (buf) >= size)
214   {
215     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
216   }
217 #elif defined (HAVE_SNPRINTF)
218   snprintf (buf, size, "vs(n)printf required");
219 #elif defined (HAVE_SRINTF)
220   sprintf (buf, "vs(n)printf required");
221   if (strlen (buf) >= size)
222   {
223     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
224   }
225 #else
226   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
227 #endif
228 }
229
230 void emitpComment (const char *fmt, ...)
231 {
232   va_list va;
233   char buffer[4096];
234   
235   va_start (va, fmt);
236   if (pb) {
237     Safe_vsnprintf (buffer, 4096, fmt, va);
238     //fprintf (stderr, "%s\n" ,buffer);
239     addpCode2pBlock (pb, newpCodeCharP (buffer));
240   }
241   va_end (va);
242 }
243
244 void emitpLabel(int key)
245 {
246         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
247 }
248
249 void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
250 {
251         if(pcop)
252                 addpCode2pBlock(pb,newpCode(poc,pcop));
253         else
254                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
255 }
256
257 void emitpcodeNULLop(PIC_OPCODE poc)
258 {
259         
260         addpCode2pBlock(pb,newpCode(poc,NULL));
261         
262 }
263
264
265 /*-----------------------------------------------------------------*/
266 /* pic14_emitcode - writes the code into a file : for now it is simple    */
267 /*-----------------------------------------------------------------*/
268 void pic14_emitcode (char *inst,char *fmt, ...)
269 {
270         va_list ap;
271         char lb[INITIAL_INLINEASM];  
272         char *lbp = lb;
273         
274         va_start(ap,fmt);   
275         
276         if (inst && *inst) {
277                 if (fmt && *fmt)
278                         sprintf(lb,"%s\t",inst);
279                 else
280                         sprintf(lb,"%s",inst);
281                 vsprintf(lb+(strlen(lb)),fmt,ap);
282         }  else
283                 vsprintf(lb,fmt,ap);
284         
285         while (isspace(*lbp)) lbp++;
286         
287         if (lbp && *lbp) 
288                 lineCurr = (lineCurr ?
289                 connectLine(lineCurr,newLineNode(lb)) :
290         (lineHead = newLineNode(lb)));
291         lineCurr->isInline = _G.inLine;
292         lineCurr->isDebug  = _G.debugLine;
293         
294         if(debug_verbose)
295                 addpCode2pBlock(pb,newpCodeCharP(lb));
296         
297         va_end(ap);
298 }
299
300 /*-----------------------------------------------------------------*/
301 /* pic14_emitDebuggerSymbol - associate the current code location  */
302 /*       with a debugger symbol                                                                            */
303 /*-----------------------------------------------------------------*/
304 void
305 pic14_emitDebuggerSymbol (char * debugSym)
306 {
307         _G.debugLine = 1;
308         pic14_emitcode ("", ";%s ==.", debugSym);
309         _G.debugLine = 0;
310 }
311
312
313 /*-----------------------------------------------------------------*/
314 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
315 /*-----------------------------------------------------------------*/
316 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
317 {
318         bool r0iu = FALSE , r1iu = FALSE;
319         bool r0ou = FALSE , r1ou = FALSE;
320         
321         /* the logic: if r0 & r1 used in the instruction
322         then we are in trouble otherwise */
323         
324         /* first check if r0 & r1 are used by this
325         instruction, in which case we are in trouble */
326         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
327                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
328         {
329                 goto endOfWorld;          
330         }
331         
332         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
333         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
334         
335         /* if no usage of r0 then return it */
336         if (!r0iu && !r0ou) {
337                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
338                 (*aopp)->type = AOP_R0;
339                 
340                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
341         }
342         
343         /* if no usage of r1 then return it */
344         if (!r1iu && !r1ou) {
345                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
346                 (*aopp)->type = AOP_R1;
347                 
348                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
349         }    
350         
351         /* now we know they both have usage */
352         /* if r0 not used in this instruction */
353         if (!r0iu) {
354                 /* push it if not already pushed */
355                 if (!_G.r0Pushed) {
356                         //pic14_emitcode ("push","%s",
357                         //                pic14_regWithIdx(R0_IDX)->dname);
358                         _G.r0Pushed++ ;
359                 }
360                 
361                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
362                 (*aopp)->type = AOP_R0;
363                 
364                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
365         }
366         
367         /* if r1 not used then */
368         
369         if (!r1iu) {
370                 /* push it if not already pushed */
371                 if (!_G.r1Pushed) {
372                         //pic14_emitcode ("push","%s",
373                         //                pic14_regWithIdx(R1_IDX)->dname);
374                         _G.r1Pushed++ ;
375                 }
376                 
377                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
378                 (*aopp)->type = AOP_R1;
379                 return pic14_regWithIdx(R1_IDX);
380         }
381         
382 endOfWorld :
383         /* I said end of world but not quite end of world yet */
384         /* if this is a result then we can push it on the stack*/
385         if (result) {
386                 (*aopp)->type = AOP_STK;        
387                 return NULL;
388         }
389         
390         /* other wise this is true end of the world */
391         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
392                 "getFreePtr should never reach here");
393         exit(0);
394 }
395
396 /*-----------------------------------------------------------------*/
397 /* newAsmop - creates a new asmOp                                                                  */
398 /*-----------------------------------------------------------------*/
399 asmop *newAsmop (short type)
400 {
401         asmop *aop;
402         
403         aop = Safe_calloc(1,sizeof(asmop));
404         aop->type = type;
405         return aop;
406 }
407
408 static void genSetDPTR(int n)
409 {
410         if (!n)
411         {
412                 pic14_emitcode(";", "Select standard DPTR");
413                 pic14_emitcode("mov", "dps, #0x00");
414         }
415         else
416         {
417                 pic14_emitcode(";", "Select alternate DPTR");
418                 pic14_emitcode("mov", "dps, #0x01");
419         }
420 }
421
422 /*-----------------------------------------------------------------*/
423 /* resolveIfx - converts an iCode ifx into a form more useful for  */
424 /*                              generating code                                                                    */
425 /*-----------------------------------------------------------------*/
426 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
427 {
428         if(!resIfx) 
429                 return;
430         
431         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
432         
433         resIfx->condition = 1;  /* assume that the ifx is true */
434         resIfx->generated = 0;  /* indicate that the ifx has not been used */
435         
436         if(!ifx) {
437                 resIfx->lbl = newiTempLabel(NULL);      /* oops, there is no ifx. so create a label */
438                                                                                         /*
439                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
440                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
441                 */
442         } else {
443                 if(IC_TRUE(ifx)) {
444                         resIfx->lbl = IC_TRUE(ifx);
445                 } else {
446                         resIfx->lbl = IC_FALSE(ifx);
447                         resIfx->condition = 0;
448                 }
449                 /*
450                 if(IC_TRUE(ifx)) 
451                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
452                 if(IC_FALSE(ifx)) 
453                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
454                 */
455         }
456         
457         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
458         
459 }
460 /*-----------------------------------------------------------------*/
461 /* pointerCode - returns the code for a pointer type                       */
462 /*-----------------------------------------------------------------*/
463 static int pointerCode (sym_link *etype)
464 {
465         
466         return PTR_TYPE(SPEC_OCLS(etype));
467         
468 }
469
470 /*-----------------------------------------------------------------*/
471 /* aopForSym - for a true symbol                                                                   */
472 /*-----------------------------------------------------------------*/
473 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
474 {
475         asmop *aop;
476         memmap *space= SPEC_OCLS(sym->etype);
477         
478         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
479         /* if already has one */
480         if (sym->aop)
481                 return sym->aop;
482         
483         /* assign depending on the storage class */
484         /* if it is on the stack or indirectly addressable */
485         /* space we need to assign either r0 or r1 to it         */    
486         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
487                 sym->aop = aop = newAsmop(0);
488                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
489                 aop->size = getSize(sym->type);
490                 
491                 /* now assign the address of the variable to 
492                 the pointer register */
493                 if (aop->type != AOP_STK) {
494                         
495                         if (sym->onStack) {
496                                 if ( _G.accInUse )
497                                         pic14_emitcode("push","acc");
498                                 
499                                 pic14_emitcode("mov","a,_bp");
500                                 pic14_emitcode("add","a,#0x%02x",
501                                         ((sym->stack < 0) ?
502                                         ((char)(sym->stack - _G.nRegsSaved )) :
503                                 ((char)sym->stack)) & 0xff);
504                                 pic14_emitcode("mov","%s,a",
505                                         aop->aopu.aop_ptr->name);
506                                 
507                                 if ( _G.accInUse )
508                                         pic14_emitcode("pop","acc");
509                         } else
510                                 pic14_emitcode("mov","%s,#%s",
511                                 aop->aopu.aop_ptr->name,
512                                 sym->rname);
513                         aop->paged = space->paged;
514                 } else
515                         aop->aopu.aop_stk = sym->stack;
516                 return aop;
517         }
518         
519         if (sym->onStack && options.stack10bit)
520         {
521                 /* It's on the 10 bit stack, which is located in
522                 * far data space.
523                 */
524                 
525                 //DEBUGpic14_emitcode(";","%d",__LINE__);
526                 
527                 if ( _G.accInUse )
528                         pic14_emitcode("push","acc");
529                 
530                 pic14_emitcode("mov","a,_bp");
531                 pic14_emitcode("add","a,#0x%02x",
532                         ((sym->stack < 0) ?
533                         ((char)(sym->stack - _G.nRegsSaved )) :
534                 ((char)sym->stack)) & 0xff);
535                 
536                 genSetDPTR(1);
537                 pic14_emitcode ("mov","dpx1,#0x40");
538                 pic14_emitcode ("mov","dph1,#0x00");
539                 pic14_emitcode ("mov","dpl1, a");
540                 genSetDPTR(0);
541                 
542                 if ( _G.accInUse )
543                         pic14_emitcode("pop","acc");
544                 
545                 sym->aop = aop = newAsmop(AOP_DPTR2);
546                 aop->size = getSize(sym->type); 
547                 return aop;
548         }
549         
550         //DEBUGpic14_emitcode(";","%d",__LINE__);
551         /* if in bit space */
552         if (IN_BITSPACE(space)) {
553                 sym->aop = aop = newAsmop (AOP_CRY);
554                 aop->aopu.aop_dir = sym->rname ;
555                 aop->size = getSize(sym->type);
556                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
557                 return aop;
558         }
559         /* if it is in direct space */
560         if (IN_DIRSPACE(space)) {
561                 sym->aop = aop = newAsmop (AOP_DIR);
562                 aop->aopu.aop_dir = sym->rname ;
563                 aop->size = getSize(sym->type);
564                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
565                 return aop;
566         }
567         
568         /* special case for a function */
569         if (IS_FUNC(sym->type)) {   
570                 
571                 sym->aop = aop = newAsmop(AOP_PCODE);
572                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
573                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
574                 PCOI(aop->aopu.pcop)->_function = 1;
575                 PCOI(aop->aopu.pcop)->index = 0;
576                 aop->size = FPTRSIZE; 
577                 /*
578                 sym->aop = aop = newAsmop(AOP_IMMD);    
579                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
580                 strcpy(aop->aopu.aop_immd,sym->rname);
581                 aop->size = FPTRSIZE; 
582                 */
583                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
584                 return aop;
585         }
586         
587         
588         /* only remaining is far space */
589         /* in which case DPTR gets the address */
590         sym->aop = aop = newAsmop(AOP_PCODE);
591         
592         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
593         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
594         PCOI(aop->aopu.pcop)->index = 0;
595         
596         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
597                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
598         
599         allocDirReg (IC_LEFT(ic));
600         
601         aop->size = FPTRSIZE; 
602         /*
603         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
604         sym->aop = aop = newAsmop(AOP_DPTR);
605         pic14_emitcode ("mov","dptr,#%s", sym->rname);
606         aop->size = getSize(sym->type);
607         
608           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
609         */
610         
611         /* if it is in code space */
612         if (IN_CODESPACE(space))
613                 aop->code = 1;
614         
615         return aop;       
616 }
617
618 /*-----------------------------------------------------------------*/
619 /* aopForRemat - rematerialzes an object                                                   */
620 /*-----------------------------------------------------------------*/
621 static asmop *aopForRemat (operand *op) // x symbol *sym)
622 {
623         symbol *sym = OP_SYMBOL(op);
624         iCode *ic = NULL;
625         asmop *aop = newAsmop(AOP_PCODE);
626         int val = 0;
627         int offset = 0;
628         
629         ic = sym->rematiCode;
630         
631         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
632         if(IS_OP_POINTER(op)) {
633                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
634         }
635         for (;;) {
636                 if (ic->op == '+') {
637                         val += (int) operandLitValue(IC_RIGHT(ic));
638                 } else if (ic->op == '-') {
639                         val -= (int) operandLitValue(IC_RIGHT(ic));
640                 } else
641                         break;
642                 
643                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
644         }
645         
646         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
647         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
648         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
649         PCOI(aop->aopu.pcop)->index = val;
650         
651         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
652                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
653                 val, IS_PTR_CONST(operandType(op)));
654         
655         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
656         
657         allocDirReg (IC_LEFT(ic));
658         
659         return aop;              
660 }
661
662 int aopIdx (asmop *aop, int offset)
663 {
664         if(!aop)
665                 return -1;
666         
667         if(aop->type !=  AOP_REG)
668                 return -2;
669         
670         return aop->aopu.aop_reg[offset]->rIdx;
671         
672 }
673 /*-----------------------------------------------------------------*/
674 /* regsInCommon - two operands have some registers in common       */
675 /*-----------------------------------------------------------------*/
676 static bool regsInCommon (operand *op1, operand *op2)
677 {
678         symbol *sym1, *sym2;
679         int i;
680         
681         /* if they have registers in common */
682         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
683                 return FALSE ;
684         
685         sym1 = OP_SYMBOL(op1);
686         sym2 = OP_SYMBOL(op2);
687         
688         if (sym1->nRegs == 0 || sym2->nRegs == 0)
689                 return FALSE ;
690         
691         for (i = 0 ; i < sym1->nRegs ; i++) {
692                 int j;
693                 if (!sym1->regs[i])
694                         continue ;
695                 
696                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
697                         if (!sym2->regs[j])
698                                 continue ;
699                         
700                         if (sym2->regs[j] == sym1->regs[i])
701                                 return TRUE ;
702                 }
703         }
704         
705         return FALSE ;
706 }
707
708 /*-----------------------------------------------------------------*/
709 /* operandsEqu - equivalent                                                                        */
710 /*-----------------------------------------------------------------*/
711 static bool operandsEqu ( operand *op1, operand *op2)
712 {
713         symbol *sym1, *sym2;
714         
715         /* if they not symbols */
716         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
717                 return FALSE;
718         
719         sym1 = OP_SYMBOL(op1);
720         sym2 = OP_SYMBOL(op2);
721         
722         /* if both are itemps & one is spilt
723         and the other is not then false */
724         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
725                 sym1->isspilt != sym2->isspilt )
726                 return FALSE ;
727         
728         /* if they are the same */
729         if (sym1 == sym2)
730                 return TRUE ;
731         
732         if (sym1->rname[0] && sym2->rname[0]
733                 && strcmp (sym1->rname, sym2->rname) == 0)
734                 return TRUE;
735         
736         
737         /* if left is a tmp & right is not */
738         if (IS_ITEMP(op1)  && 
739                 !IS_ITEMP(op2) &&
740                 sym1->isspilt  &&
741                 (sym1->usl.spillLoc == sym2))
742                 return TRUE;
743         
744         if (IS_ITEMP(op2)  && 
745                 !IS_ITEMP(op1) &&
746                 sym2->isspilt  &&
747                 sym1->level > 0 &&
748                 (sym2->usl.spillLoc == sym1))
749                 return TRUE ;
750         
751         return FALSE ;
752 }
753
754 /*-----------------------------------------------------------------*/
755 /* pic14_sameRegs - two asmops have the same registers             */
756 /*-----------------------------------------------------------------*/
757 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
758 {
759         int i;
760         
761         if (aop1 == aop2)
762                 return TRUE ;
763         
764         if (aop1->type != AOP_REG ||
765                 aop2->type != AOP_REG )
766                 return FALSE ;
767         
768         if (aop1->size != aop2->size )
769                 return FALSE ;
770         
771         for (i = 0 ; i < aop1->size ; i++ )
772                 if (aop1->aopu.aop_reg[i] !=
773                         aop2->aopu.aop_reg[i] )
774                         return FALSE ;
775                 
776                 return TRUE ;
777 }
778
779 /*-----------------------------------------------------------------*/
780 /* aopOp - allocates an asmop for an operand  :                    */
781 /*-----------------------------------------------------------------*/
782 void aopOp (operand *op, iCode *ic, bool result)
783 {
784         asmop *aop;
785         symbol *sym;
786         int i;
787         
788         if (!op)
789                 return ;
790         
791         /* if this a literal */
792         if (IS_OP_LITERAL(op)) {
793                 op->aop = aop = newAsmop(AOP_LIT);
794                 aop->aopu.aop_lit = op->operand.valOperand;
795                 aop->size = getSize(operandType(op));
796                 return;
797         }
798         
799         {
800                 sym_link *type = operandType(op);
801                 if(IS_PTR_CONST(type))
802                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
803         }
804         
805         /* if already has a asmop then continue */
806         if (op->aop)
807                 return ;
808         
809         /* if the underlying symbol has a aop */
810         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
811                 DEBUGpic14_emitcode(";","%d",__LINE__);
812                 op->aop = OP_SYMBOL(op)->aop;
813                 return;
814         }
815         
816         /* if this is a true symbol */
817         if (IS_TRUE_SYMOP(op)) {          
818                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
819                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
820                 return ;
821         }
822         
823         /* this is a temporary : this has
824         only four choices :
825         a) register
826         b) spillocation
827         c) rematerialize 
828         d) conditional   
829         e) can be a return use only */
830         
831         sym = OP_SYMBOL(op);
832         
833         
834         /* if the type is a conditional */
835         if (sym->regType == REG_CND) {
836                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
837                 aop->size = 0;
838                 return;
839         }
840         
841         /* if it is spilt then two situations
842         a) is rematerialize 
843         b) has a spill location */
844         if (sym->isspilt || sym->nRegs == 0) {
845                 
846                 DEBUGpic14_emitcode(";","%d",__LINE__);
847                 /* rematerialize it NOW */
848                 if (sym->remat) {
849                         
850                         sym->aop = op->aop = aop = aopForRemat (op);
851                         aop->size = getSize(sym->type);
852                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
853                         return;
854                 }
855                 
856                 if (sym->accuse) {
857                         int i;
858                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
859                         aop->size = getSize(sym->type);
860                         for ( i = 0 ; i < 2 ; i++ )
861                                 aop->aopu.aop_str[i] = accUse[i];
862                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
863                         return;  
864                 }
865                 
866                 if (sym->ruonly ) {
867                         if(sym->isptr) {        // && sym->uptr 
868                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
869                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
870                                 
871                                 //PCOI(aop->aopu.pcop)->_const = 0;
872                                 //PCOI(aop->aopu.pcop)->index = 0;
873                                 /*
874                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
875                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
876                                 */
877                                 //allocDirReg (IC_LEFT(ic));
878                                 
879                                 aop->size = getSize(sym->type);
880                                 DEBUGpic14_emitcode(";","%d",__LINE__);
881                                 return;
882                                 
883                         } else {
884                                 
885                                 unsigned i;
886                                 
887                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
888                                 aop->size = getSize(sym->type);
889                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
890                                         aop->aopu.aop_str[i] = fReturn[i];
891                                 
892                                 DEBUGpic14_emitcode(";","%d",__LINE__);
893                                 return;
894                         }
895                 }
896                 
897                 /* else spill location  */
898                 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
899                         /* force a new aop if sizes differ */
900                         sym->usl.spillLoc->aop = NULL;
901                 }
902                 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
903                         __FUNCTION__,__LINE__,
904                         sym->usl.spillLoc->rname,
905                         sym->rname, sym->usl.spillLoc->offset);
906                 
907                 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
908                 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
909                 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
910                         getSize(sym->type), 
911                         sym->usl.spillLoc->offset);
912                 aop->size = getSize(sym->type);
913                 
914                 return;
915         }
916         
917         {
918                 sym_link *type = operandType(op);
919                 if(IS_PTR_CONST(type)) 
920                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
921         }
922         
923         /* must be in a register */
924         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
925         sym->aop = op->aop = aop = newAsmop(AOP_REG);
926         aop->size = sym->nRegs;
927         for ( i = 0 ; i < sym->nRegs ;i++)
928                 aop->aopu.aop_reg[i] = sym->regs[i];
929 }
930
931 /*-----------------------------------------------------------------*/
932 /* freeAsmop - free up the asmop given to an operand                       */
933 /*----------------------------------------------------------------*/
934 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
935 {       
936         asmop *aop ;
937         
938         if (!op)
939                 aop = aaop;
940         else 
941                 aop = op->aop;
942         
943         if (!aop)
944                 return ;
945         
946         if (aop->freed)
947                 goto dealloc; 
948         
949         aop->freed = 1;
950         
951         /* depending on the asmop type only three cases need work AOP_RO
952         , AOP_R1 && AOP_STK */
953 #if 0
954         switch (aop->type) {
955         case AOP_R0 :
956                 if (_G.r0Pushed ) {
957                         if (pop) {
958                                 pic14_emitcode ("pop","ar0");     
959                                 _G.r0Pushed--;
960                         }
961                 }
962                 bitVectUnSetBit(ic->rUsed,R0_IDX);
963                 break;
964                 
965         case AOP_R1 :
966                 if (_G.r1Pushed ) {
967                         if (pop) {
968                                 pic14_emitcode ("pop","ar1");
969                                 _G.r1Pushed--;
970                         }
971                 }
972                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
973                 break;
974                 
975         case AOP_STK :
976                 {
977                         int sz = aop->size;      
978                         int stk = aop->aopu.aop_stk + aop->size;
979                         bitVectUnSetBit(ic->rUsed,R0_IDX);
980                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
981                         
982                         getFreePtr(ic,&aop,FALSE);
983                         
984                         if (options.stack10bit)
985                         {
986                                 /* I'm not sure what to do here yet... */
987                                 /* #STUB */
988                                 fprintf(stderr, 
989                                         "*** Warning: probably generating bad code for "
990                                         "10 bit stack mode.\n");
991                         }
992                         
993                         if (stk) {
994                                 pic14_emitcode ("mov","a,_bp");
995                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
996                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
997                         } else {
998                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
999                         }
1000                         
1001                         while (sz--) {
1002                                 pic14_emitcode("pop","acc");
1003                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1004                                 if (!sz) break;
1005                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1006                         }
1007                         op->aop = aop;
1008                         freeAsmop(op,NULL,ic,TRUE);
1009                         if (_G.r0Pushed) {
1010                                 pic14_emitcode("pop","ar0");
1011                                 _G.r0Pushed--;
1012                         }
1013                         
1014                         if (_G.r1Pushed) {
1015                                 pic14_emitcode("pop","ar1");
1016                                 _G.r1Pushed--;
1017                         }         
1018                 }
1019         }
1020 #endif
1021         
1022 dealloc:
1023         /* all other cases just dealloc */
1024         if (op ) {
1025                 op->aop = NULL;
1026                 if (IS_SYMOP(op)) {
1027                         OP_SYMBOL(op)->aop = NULL;      
1028                         /* if the symbol has a spill */
1029                         if (SPIL_LOC(op))
1030                                 SPIL_LOC(op)->aop = NULL;
1031                 }
1032         }
1033 }
1034
1035 /*-----------------------------------------------------------------*/
1036 /* aopGet - for fetching value of the aop                                                  */
1037 /*-----------------------------------------------------------------*/
1038 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1039 {
1040         char *s = buffer ;
1041         char *rs;
1042         
1043         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1044         /* offset is greater than
1045         size then zero */
1046         if (offset > (aop->size - 1) &&
1047                 aop->type != AOP_LIT)
1048                 return zero;
1049         
1050         /* depending on type */
1051         switch (aop->type) {
1052                 
1053         case AOP_R0:
1054         case AOP_R1:
1055                 DEBUGpic14_emitcode(";","%d",__LINE__);
1056                 /* if we need to increment it */           
1057                 while (offset > aop->coff) {            
1058                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1059                         aop->coff++;
1060                 }
1061                 
1062                 while (offset < aop->coff) {
1063                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1064                         aop->coff--;
1065                 }
1066                 
1067                 aop->coff = offset ;
1068                 if (aop->paged) {
1069                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1070                         return (dname ? "acc" : "a");
1071                 }               
1072                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1073                 rs = Safe_calloc(1,strlen(s)+1);
1074                 strcpy(rs,s);   
1075                 return rs;
1076                 
1077         case AOP_DPTR:
1078         case AOP_DPTR2:
1079                 DEBUGpic14_emitcode(";","%d",__LINE__);
1080                 if (aop->type == AOP_DPTR2)
1081                 {
1082                         genSetDPTR(1);
1083                 }
1084                 
1085                 while (offset > aop->coff) {
1086                         pic14_emitcode ("inc","dptr");
1087                         aop->coff++;
1088                 }
1089                 
1090                 while (offset < aop->coff) {            
1091                         pic14_emitcode("lcall","__decdptr");
1092                         aop->coff--;
1093                 }
1094                 
1095                 aop->coff = offset;
1096                 if (aop->code) {
1097                         pic14_emitcode("clr","a");
1098                         pic14_emitcode("movc","a,@a+dptr");
1099                 }
1100                 else {
1101                         pic14_emitcode("movx","a,@dptr");
1102                 }
1103                 
1104                 if (aop->type == AOP_DPTR2)
1105                 {
1106                         genSetDPTR(0);
1107                 }
1108                 
1109                 return (dname ? "acc" : "a");
1110                 
1111                 
1112         case AOP_IMMD:
1113                 if (bit16) 
1114                         sprintf (s,"%s",aop->aopu.aop_immd);
1115                 else
1116                         if (offset) 
1117                                 sprintf(s,"(%s >> %d)",
1118                                 aop->aopu.aop_immd,
1119                                 offset*8);
1120                         else
1121                                 sprintf(s,"%s",
1122                                 aop->aopu.aop_immd);
1123                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1124                         rs = Safe_calloc(1,strlen(s)+1);
1125                         strcpy(rs,s);   
1126                         return rs;
1127                         
1128         case AOP_DIR:
1129                 if (offset) {
1130                         sprintf(s,"(%s + %d)",
1131                                 aop->aopu.aop_dir,
1132                                 offset);
1133                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1134                 } else
1135                         sprintf(s,"%s",aop->aopu.aop_dir);
1136                 rs = Safe_calloc(1,strlen(s)+1);
1137                 strcpy(rs,s);   
1138                 return rs;
1139                 
1140         case AOP_REG:
1141                 //if (dname) 
1142                 //        return aop->aopu.aop_reg[offset]->dname;
1143                 //else
1144                 return aop->aopu.aop_reg[offset]->name;
1145                 
1146         case AOP_CRY:
1147                 //pic14_emitcode(";","%d",__LINE__);
1148                 return aop->aopu.aop_dir;
1149                 
1150         case AOP_ACC:
1151                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1152                 return "AOP_accumulator_bug";
1153                 
1154         case AOP_LIT:
1155                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1156                 rs = Safe_calloc(1,strlen(s)+1);
1157                 strcpy(rs,s);   
1158                 return rs;
1159                 
1160         case AOP_STR:
1161                 aop->coff = offset ;
1162                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1163                         dname)
1164                         return "acc";
1165                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1166                 
1167                 return aop->aopu.aop_str[offset];
1168                 
1169         case AOP_PCODE:
1170                 {
1171                         pCodeOp *pcop = aop->aopu.pcop;
1172                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1173                         if(pcop->name) {
1174                                 if (offset) {
1175                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1176                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1177                                 } else {
1178                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1179                                         sprintf(s,"%s", pcop->name);
1180                                 }
1181                         } else
1182                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1183                         
1184                 }
1185                 rs = Safe_calloc(1,strlen(s)+1);
1186                 strcpy(rs,s);   
1187                 return rs;
1188                 
1189   }
1190   
1191   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1192           "aopget got unsupported aop->type");
1193   exit(0);
1194 }
1195
1196
1197 /*-----------------------------------------------------------------*/
1198 /* popGetTempReg - create a new temporary pCodeOp                                  */
1199 /*-----------------------------------------------------------------*/
1200 pCodeOp *popGetTempReg(void)
1201 {
1202         
1203         pCodeOp *pcop;
1204         
1205         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1206         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1207                 PCOR(pcop)->r->wasUsed=1;
1208                 PCOR(pcop)->r->isFree=0;
1209         }
1210         
1211         return pcop;
1212 }
1213
1214 /*-----------------------------------------------------------------*/
1215 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1216 /*-----------------------------------------------------------------*/
1217 void popReleaseTempReg(pCodeOp *pcop)
1218 {
1219         
1220         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1221                 PCOR(pcop)->r->isFree = 1;
1222         
1223 }
1224 /*-----------------------------------------------------------------*/
1225 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1226 /*-----------------------------------------------------------------*/
1227 pCodeOp *popGetLabel(unsigned int key)
1228 {
1229         
1230         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1231         
1232         if(key>(unsigned int)max_key)
1233                 max_key = key;
1234         
1235         return newpCodeOpLabel(NULL,key+100+labelOffset);
1236 }
1237
1238 /*-------------------------------------------------------------------*/
1239 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1240 /*-------------------------------------------------------------------*/
1241 pCodeOp *popGetHighLabel(unsigned int key)
1242 {
1243         pCodeOp *pcop;
1244         pcop = popGetLabel(key);
1245         PCOLAB(pcop)->offset = 1;
1246         return pcop;
1247 }
1248
1249 /*-----------------------------------------------------------------*/
1250 /* popGetLit - asm operator to pcode operator conversion                           */
1251 /*-----------------------------------------------------------------*/
1252 pCodeOp *popGetLit(unsigned int lit)
1253 {
1254         
1255         return newpCodeOpLit(lit);
1256 }
1257
1258 /*-----------------------------------------------------------------*/
1259 /* popGetImmd - asm operator to pcode immediate conversion                 */
1260 /*-----------------------------------------------------------------*/
1261 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1262 {
1263         
1264         return newpCodeOpImmd(name, offset,index, 0, is_func);
1265 }
1266
1267
1268 /*-----------------------------------------------------------------*/
1269 /* popGetWithString - asm operator to pcode operator conversion                    */
1270 /*-----------------------------------------------------------------*/
1271 pCodeOp *popGetWithString(char *str, int isExtern)
1272 {
1273         pCodeOp *pcop;
1274         
1275         
1276         if(!str) {
1277                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1278                 exit (1);
1279         }
1280         
1281         pcop = newpCodeOp(str,PO_STR);
1282         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1283         
1284         return pcop;
1285 }
1286
1287 /*-----------------------------------------------------------------*/
1288 /* popRegFromString -                                                                                      */
1289 /*-----------------------------------------------------------------*/
1290 pCodeOp *popRegFromString(char *str, int size, int offset)
1291 {
1292         
1293         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1294         pcop->type = PO_DIR;
1295         
1296         DEBUGpic14_emitcode(";","%d",__LINE__);
1297         
1298         if(!str)
1299                 str = "BAD_STRING";
1300         
1301         pcop->name = Safe_calloc(1,strlen(str)+1);
1302         strcpy(pcop->name,str);
1303         
1304         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1305         
1306         PCOR(pcop)->r = dirregWithName(pcop->name);
1307         if(PCOR(pcop)->r == NULL) {
1308                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1309                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1310                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1311         } else {
1312                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1313         }
1314         PCOR(pcop)->instance = offset;
1315         
1316         return pcop;
1317 }
1318
1319 /*-----------------------------------------------------------------*/
1320 /*-----------------------------------------------------------------*/
1321 pCodeOp *popRegFromIdx(int rIdx)
1322 {
1323         pCodeOp *pcop;
1324         
1325         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1326                 __FUNCTION__,__LINE__,rIdx);
1327         
1328         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1329         
1330         PCOR(pcop)->rIdx = rIdx;
1331         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1332         PCOR(pcop)->r->isFree = 0;
1333         PCOR(pcop)->r->wasUsed = 1;
1334         
1335         pcop->type = PCOR(pcop)->r->pc_type;
1336         
1337         
1338         return pcop;
1339 }
1340
1341 /*-----------------------------------------------------------------*/
1342 /* popGet - asm operator to pcode operator conversion                      */
1343 /*-----------------------------------------------------------------*/
1344 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1345 {
1346         //char *s = buffer ;
1347         //char *rs;
1348         
1349         pCodeOp *pcop;
1350         
1351         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1352         /* offset is greater than
1353         size then zero */
1354
1355         if (!(offset >= 0 && ((offset < aop->size) || (aop->size == 0))))
1356         {
1357           fprintf (stderr, "%s:%u: offset=%d, aop-type:%s, size:%d\n", __FILE__, __LINE__, offset, AopType (aop->type), aop->size);
1358         }
1359         assert (offset >= 0 && ((offset < aop->size) || (aop->size == 0)));
1360         
1361         /* XXX: still needed for BIT operands (AOP_CRY) */
1362         if (offset > (aop->size - 1) &&
1363                 aop->type != AOP_LIT)
1364                 return NULL;  //zero;
1365         
1366         /* depending on type */
1367         switch (aop->type) {
1368                 
1369         case AOP_R0:
1370         case AOP_R1:
1371         case AOP_DPTR:
1372         case AOP_DPTR2:
1373         case AOP_ACC:
1374                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1375                 return NULL;
1376                 
1377         case AOP_IMMD:
1378                 DEBUGpic14_emitcode(";","%d",__LINE__);
1379                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1380                 
1381         case AOP_DIR:
1382                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1383 #if 0
1384                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1385                 pcop->type = PO_DIR;
1386                 
1387                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1388                 strcpy(pcop->name,aop->aopu.aop_dir);   
1389                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1390                 if(PCOR(pcop)->r == NULL) {
1391                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1392                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1393                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1394                 } else {
1395                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1396                 }
1397                 PCOR(pcop)->instance = offset;
1398                 
1399                 return pcop;
1400 #endif
1401                 
1402         case AOP_REG:
1403                 {
1404                         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1405                         
1406                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1407                         PCOR(pcop)->rIdx = rIdx;
1408                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1409                         PCOR(pcop)->r->wasUsed=1;
1410                         PCOR(pcop)->r->isFree=0;
1411                         
1412                         PCOR(pcop)->instance = offset;
1413                         pcop->type = PCOR(pcop)->r->pc_type;
1414                         //rs = aop->aopu.aop_reg[offset]->name;
1415                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1416                         return pcop;
1417                 }
1418                 
1419         case AOP_CRY:
1420                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1421                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1422                 //if(PCOR(pcop)->r == NULL)
1423                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1424                 return pcop;
1425                 
1426         case AOP_LIT:
1427                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1428                 
1429         case AOP_STR:
1430                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1431                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1432                 /*
1433                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1434                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1435                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1436                 pcop->type = PCOR(pcop)->r->pc_type;
1437                 pcop->name = PCOR(pcop)->r->name;
1438                 
1439                   return pcop;
1440                 */
1441                 
1442         case AOP_PCODE:
1443                 pcop = NULL;
1444                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1445                         __LINE__, 
1446                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1447                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1448                 switch (aop->aopu.pcop->type)
1449                 {
1450                 case PO_IMMEDIATE:
1451                   pcop = pCodeOpCopy (aop->aopu.pcop);
1452                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1453                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1454                   PCOI(pcop)->index += offset;
1455                   //PCOI(pcop)->offset = 0;
1456                   break;
1457                 case PO_DIR:
1458                   pcop = pCodeOpCopy (aop->aopu.pcop);
1459                   PCOR(pcop)->instance = offset;
1460                   break;
1461                 default:
1462                   assert ( !"unhandled pCode type" );
1463                   break;
1464                 } // switch
1465                 return pcop;
1466         }
1467         
1468         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1469                 "popGet got unsupported aop->type");
1470         exit(0);
1471 }
1472
1473 /*-----------------------------------------------------------------*/
1474 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1475 /*              (for non-PO_IMMEDIATEs this is the same as poGet)  */
1476 /*-----------------------------------------------------------------*/
1477 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1478 {
1479   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1480   {
1481     pCodeOp *pcop = aop->aopu.pcop;
1482     pcop = pCodeOpCopy (pcop);
1483     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1484      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1485     PCOI(pcop)->offset += offset;
1486     PCOI(pcop)->index += index;
1487     return pcop;
1488   } else {
1489     return popGet (aop, offset + index);
1490   }
1491 }
1492
1493 /*-----------------------------------------------------------------*/
1494 /* aopPut - puts a string for a aop                                                        */
1495 /*-----------------------------------------------------------------*/
1496 void aopPut (asmop *aop, char *s, int offset)
1497 {
1498         char *d = buffer ;
1499         symbol *lbl ;
1500         
1501         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1502         
1503         if (aop->size && offset > ( aop->size - 1)) {
1504                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1505                         "aopPut got offset > aop->size");
1506                 exit(0);
1507         }
1508         
1509         /* will assign value to value */
1510         /* depending on where it is ofcourse */
1511         switch (aop->type) {
1512         case AOP_DIR:
1513                 if (offset) {
1514                         sprintf(d,"(%s + %d)",
1515                                 aop->aopu.aop_dir,offset);
1516                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1517                         
1518                 } else
1519                         sprintf(d,"%s",aop->aopu.aop_dir);
1520                 
1521                 if (strcmp(d,s)) {
1522                         DEBUGpic14_emitcode(";","%d",__LINE__);
1523                         if(strcmp(s,"W"))
1524                                 pic14_emitcode("movf","%s,w",s);
1525                         pic14_emitcode("movwf","%s",d);
1526                         
1527                         if(strcmp(s,"W")) {
1528                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1529                                 if(offset >= aop->size) {
1530                                         emitpcode(POC_CLRF,popGet(aop,offset));
1531                                         break;
1532                                 } else
1533                                         emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1534                         }
1535                         
1536                         emitpcode(POC_MOVWF,popGet(aop,offset));
1537                         
1538                         
1539                 }
1540                 break;
1541                 
1542         case AOP_REG:
1543                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1544                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1545                         /*
1546                         if (*s == '@'             ||
1547                         strcmp(s,"r0") == 0 ||
1548                         strcmp(s,"r1") == 0 ||
1549                         strcmp(s,"r2") == 0 ||
1550                         strcmp(s,"r3") == 0 ||
1551                         strcmp(s,"r4") == 0 ||
1552                         strcmp(s,"r5") == 0 ||
1553                         strcmp(s,"r6") == 0 || 
1554                         strcmp(s,"r7") == 0 )
1555                         pic14_emitcode("mov","%s,%s  ; %d",
1556                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1557                         else
1558                         */
1559                         
1560                         if(strcmp(s,"W")==0 )
1561                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1562                         
1563                         pic14_emitcode("movwf","%s",
1564                                 aop->aopu.aop_reg[offset]->name);
1565                         
1566                         if(strcmp(s,zero)==0) {
1567                                 emitpcode(POC_CLRF,popGet(aop,offset));
1568                                 
1569                         } else if(strcmp(s,"W")==0) {
1570                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1571                                 pcop->type = PO_GPR_REGISTER;
1572                                 
1573                                 PCOR(pcop)->rIdx = -1;
1574                                 PCOR(pcop)->r = NULL;
1575                                 
1576                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1577                                 pcop->name = Safe_strdup(s);
1578                                 emitpcode(POC_MOVFW,pcop);
1579                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1580                         } else if(strcmp(s,one)==0) {
1581                                 emitpcode(POC_CLRF,popGet(aop,offset));
1582                                 emitpcode(POC_INCF,popGet(aop,offset));
1583                         } else {
1584                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1585                         }
1586                 }
1587                 break;
1588                 
1589         case AOP_DPTR:
1590         case AOP_DPTR2:
1591                 
1592                 if (aop->type == AOP_DPTR2)
1593                 {
1594                         genSetDPTR(1);
1595                 }
1596                 
1597                 if (aop->code) {
1598                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1599                                 "aopPut writting to code space");
1600                         exit(0);
1601                 }
1602                 
1603                 while (offset > aop->coff) {
1604                         aop->coff++;
1605                         pic14_emitcode ("inc","dptr");
1606                 }
1607                 
1608                 while (offset < aop->coff) {
1609                         aop->coff-- ;
1610                         pic14_emitcode("lcall","__decdptr");
1611                 }
1612                 
1613                 aop->coff = offset;
1614                 
1615                 /* if not in accumulater */
1616                 MOVA(s);
1617                 
1618                 pic14_emitcode ("movx","@dptr,a");
1619                 
1620                 if (aop->type == AOP_DPTR2)
1621                 {
1622                         genSetDPTR(0);
1623                 }
1624                 break;
1625                 
1626         case AOP_R0:
1627         case AOP_R1:
1628                 while (offset > aop->coff) {
1629                         aop->coff++;
1630                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1631                 }
1632                 while (offset < aop->coff) {
1633                         aop->coff-- ;
1634                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1635                 }
1636                 aop->coff = offset;
1637                 
1638                 if (aop->paged) {
1639                         MOVA(s);                         
1640                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1641                         
1642                 } else
1643                         if (*s == '@') {
1644                                 MOVA(s);
1645                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1646                         } else
1647                                 if (strcmp(s,"r0") == 0 ||
1648                                         strcmp(s,"r1") == 0 ||
1649                                         strcmp(s,"r2") == 0 ||
1650                                         strcmp(s,"r3") == 0 ||
1651                                         strcmp(s,"r4") == 0 ||
1652                                         strcmp(s,"r5") == 0 ||
1653                                         strcmp(s,"r6") == 0 || 
1654                                         strcmp(s,"r7") == 0 ) {
1655                                         char buffer[10];
1656                                         sprintf(buffer,"a%s",s);
1657                                         pic14_emitcode("mov","@%s,%s",
1658                                                 aop->aopu.aop_ptr->name,buffer);
1659                                 } else
1660                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1661                                 
1662                                 break;
1663                                 
1664         case AOP_STK:
1665                 if (strcmp(s,"a") == 0)
1666                         pic14_emitcode("push","acc");
1667                 else
1668                         pic14_emitcode("push","%s",s);
1669                 
1670                 break;
1671                 
1672         case AOP_CRY:
1673                 /* if bit variable */
1674                 if (!aop->aopu.aop_dir) {
1675                         pic14_emitcode("clr","a");
1676                         pic14_emitcode("rlc","a");
1677                 } else {
1678                         if (s == zero) 
1679                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1680                         else
1681                                 if (s == one)
1682                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1683                                 else
1684                                         if (!strcmp(s,"c"))
1685                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1686                                         else {
1687                                                 lbl = newiTempLabel(NULL);
1688                                                 
1689                                                 if (strcmp(s,"a")) {
1690                                                         MOVA(s);
1691                                                 }
1692                                                 pic14_emitcode("clr","c");
1693                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1694                                                 pic14_emitcode("cpl","c");
1695                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1696                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1697                                         }
1698                 }
1699                 break;
1700                 
1701         case AOP_STR:
1702                 aop->coff = offset;
1703                 if (strcmp(aop->aopu.aop_str[offset],s))
1704                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1705                 break;
1706                 
1707         case AOP_ACC:
1708                 aop->coff = offset;
1709                 if (!offset && (strcmp(s,"acc") == 0))
1710                         break;
1711                 
1712                 if (strcmp(aop->aopu.aop_str[offset],s))
1713                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1714                 break;
1715                 
1716         default :
1717                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1718                         "aopPut got unsupported aop->type");
1719                 exit(0);
1720         }
1721         
1722 }
1723
1724 /*-----------------------------------------------------------------*/
1725 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1726 /*-----------------------------------------------------------------*/
1727 void mov2w (asmop *aop, int offset)
1728 {
1729         
1730         if(!aop)
1731                 return;
1732         
1733         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1734         
1735         if ( aop_isLitLike (aop) )
1736                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1737         else
1738                 emitpcode(POC_MOVFW,popGet(aop,offset));
1739         
1740 }
1741
1742 /*-----------------------------------------------------------------*/
1743 /* reAdjustPreg - points a register back to where it should        */
1744 /*-----------------------------------------------------------------*/
1745 static void reAdjustPreg (asmop *aop)
1746 {
1747         int size ;
1748         
1749         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1750         aop->coff = 0;
1751         if ((size = aop->size) <= 1)
1752                 return ;
1753         size-- ;
1754         switch (aop->type) {
1755         case AOP_R0 :
1756         case AOP_R1 :
1757                 while (size--)
1758                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1759                 break;                  
1760         case AOP_DPTR :
1761         case AOP_DPTR2:
1762                 if (aop->type == AOP_DPTR2)
1763                 {
1764                         genSetDPTR(1);
1765                 } 
1766                 while (size--)
1767                 {
1768                         pic14_emitcode("lcall","__decdptr");
1769                 }
1770                 
1771                 if (aop->type == AOP_DPTR2)
1772                 {
1773                         genSetDPTR(0);
1774                 }
1775                 break;
1776                 
1777         }
1778         
1779 }
1780
1781
1782 #if 0
1783 /*-----------------------------------------------------------------*/
1784 /* opIsGptr: returns non-zero if the passed operand is             */
1785 /* a generic pointer type.                                         */
1786 /*-----------------------------------------------------------------*/ 
1787 static int opIsGptr(operand *op)
1788 {
1789         sym_link *type = operandType(op);
1790         
1791         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1792         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1793         {
1794                 return 1;
1795         }
1796         return 0;          
1797 }
1798 #endif
1799
1800 /*-----------------------------------------------------------------*/
1801 /* pic14_getDataSize - get the operand data size                   */
1802 /*-----------------------------------------------------------------*/
1803 int pic14_getDataSize(operand *op)
1804 {
1805         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1806         
1807         
1808         return AOP_SIZE(op);
1809         
1810         // tsd- in the pic port, the genptr size is 1, so this code here
1811         // fails. ( in the 8051 port, the size was 4).
1812 #if 0
1813         int size;
1814         size = AOP_SIZE(op);
1815         if (size == GPTRSIZE)
1816         {
1817                 sym_link *type = operandType(op);
1818                 if (IS_GENPTR(type))
1819                 {
1820                         /* generic pointer; arithmetic operations
1821                         * should ignore the high byte (pointer type).
1822                         */
1823                         size--;
1824                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1825                 }
1826         }
1827         return size;
1828 #endif
1829 }
1830
1831 /*-----------------------------------------------------------------*/
1832 /* pic14_outAcc - output Acc                                       */
1833 /*-----------------------------------------------------------------*/
1834 void pic14_outAcc(operand *result)
1835 {
1836         int size,offset;
1837         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1838         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1839         
1840         
1841         size = pic14_getDataSize(result);
1842         if(size){
1843                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1844                 size--;
1845                 offset = 1;
1846                 /* unsigned or positive */
1847                 while(size--)
1848                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1849         }
1850         
1851 }
1852
1853 /*-----------------------------------------------------------------*/
1854 /* pic14_outBitC - output a bit C                                  */
1855 /*-----------------------------------------------------------------*/
1856 void pic14_outBitC(operand *result)
1857 {
1858         
1859         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1860         /* if the result is bit */
1861         if (AOP_TYPE(result) == AOP_CRY) 
1862                 aopPut(AOP(result),"c",0);
1863         else {
1864                 pic14_emitcode("clr","a  ; %d", __LINE__);
1865                 pic14_emitcode("rlc","a");
1866                 pic14_outAcc(result);
1867         }
1868 }
1869
1870 /*-----------------------------------------------------------------*/
1871 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1872 /*-----------------------------------------------------------------*/
1873 void pic14_toBoolean(operand *oper)
1874 {
1875         int size = AOP_SIZE(oper) - 1;
1876         int offset = 1;
1877         
1878         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1879         
1880         if ( AOP_TYPE(oper) != AOP_ACC) {
1881                 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1882         }
1883         while (size--) {
1884                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1885         }
1886 }
1887
1888
1889 /*-----------------------------------------------------------------*/
1890 /* genNot - generate code for ! operation                          */
1891 /*-----------------------------------------------------------------*/
1892 static void genNot (iCode *ic)
1893 {
1894         symbol *tlbl;
1895         int size;
1896
1897         FENTRY;
1898         
1899         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1900         /* assign asmOps to operand & result */
1901         aopOp (IC_LEFT(ic),ic,FALSE);
1902         aopOp (IC_RESULT(ic),ic,TRUE);
1903         
1904         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1905         /* if in bit space then a special case */
1906         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1907                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1908                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1909                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1910                 } else {
1911                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1912                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1913                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1914                 }
1915                 goto release;
1916         }
1917         
1918         size = AOP_SIZE(IC_LEFT(ic));
1919         if(size == 1) {
1920                 emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1921                 emitpcode(POC_ANDLW,popGetLit(1));
1922                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1923                 goto release;
1924         }
1925         pic14_toBoolean(IC_LEFT(ic));
1926         
1927         tlbl = newiTempLabel(NULL);
1928         pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1929         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1930         pic14_outBitC(IC_RESULT(ic));
1931         
1932 release:        
1933         /* release the aops */
1934         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1935         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1936 }
1937
1938
1939 /*-----------------------------------------------------------------*/
1940 /* genCpl - generate code for complement                                                   */
1941 /*-----------------------------------------------------------------*/
1942 static void genCpl (iCode *ic)
1943 {
1944         operand *left, *result;
1945         int size, offset=0;  
1946         
1947         FENTRY;
1948         
1949         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1950         aopOp((left = IC_LEFT(ic)),ic,FALSE);
1951         aopOp((result=IC_RESULT(ic)),ic,TRUE);
1952         
1953         /* if both are in bit space then 
1954         a special case */
1955         if (AOP_TYPE(result) == AOP_CRY &&
1956                 AOP_TYPE(left) == AOP_CRY ) { 
1957                 
1958                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1959                 pic14_emitcode("cpl","c"); 
1960                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1961                 goto release; 
1962         } 
1963         
1964         size = AOP_SIZE(result);
1965         while (size--) {
1966                 
1967                 if(AOP_TYPE(left) == AOP_ACC) 
1968                         emitpcode(POC_XORLW, popGetLit(0xff));
1969                 else
1970                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
1971                 
1972                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1973                 offset++;
1974         }
1975         
1976         
1977 release:
1978         /* release the aops */
1979         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1980         freeAsmop(result,NULL,ic,TRUE);
1981 }
1982
1983 /*-----------------------------------------------------------------*/
1984 /* genUminusFloat - unary minus for floating points                        */
1985 /*-----------------------------------------------------------------*/
1986 static void genUminusFloat(operand *op,operand *result)
1987 {
1988         int size ,offset =0 ;
1989         char *l;
1990         
1991         FENTRY;
1992
1993         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1994         /* for this we just need to flip the 
1995         first it then copy the rest in place */
1996         size = AOP_SIZE(op) - 1;
1997         l = aopGet(AOP(op),3,FALSE,FALSE);
1998         
1999         MOVA(l);          
2000         
2001         pic14_emitcode("cpl","acc.7");
2002         aopPut(AOP(result),"a",3);      
2003         
2004         while(size--) {
2005                 aopPut(AOP(result),
2006                         aopGet(AOP(op),offset,FALSE,FALSE),
2007                         offset);
2008                 offset++;
2009         }                
2010 }
2011
2012 /*-----------------------------------------------------------------*/
2013 /* genUminus - unary minus code generation                                                 */
2014 /*-----------------------------------------------------------------*/
2015 static void genUminus (iCode *ic)
2016 {
2017         int size, i;
2018         sym_link *optype, *rtype;
2019         
2020         FENTRY;
2021         
2022         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2023         /* assign asmops */
2024         aopOp(IC_LEFT(ic),ic,FALSE);
2025         aopOp(IC_RESULT(ic),ic,TRUE);
2026         
2027         /* if both in bit space then special
2028         case */
2029         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2030                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2031                 
2032                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2033                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2034                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2035                 
2036                 goto release; 
2037         } 
2038         
2039         optype = operandType(IC_LEFT(ic));
2040         rtype = operandType(IC_RESULT(ic));
2041         
2042         /* if float then do float stuff */
2043         if (IS_FLOAT(optype)) {
2044                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2045                 goto release;
2046         }
2047         
2048         /* otherwise subtract from zero by taking the 2's complement */
2049         size = AOP_SIZE(IC_LEFT(ic));
2050         
2051         for(i=0; i<size; i++) {
2052                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2053                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2054                 else {
2055                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2056                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2057                 }
2058         }
2059         
2060         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2061         for(i=1; i<size; i++) {
2062                 emitSKPNZ;
2063                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2064         }
2065         
2066 release:
2067         /* release the aops */
2068         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2069         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2070 }
2071
2072 /*-----------------------------------------------------------------*/
2073 /* saveRegisters - will look for a call and save the registers     */
2074 /*-----------------------------------------------------------------*/
2075 static void saveRegisters(iCode *lic) 
2076 {
2077         int i;
2078         iCode *ic;
2079         bitVect *rsave;
2080         sym_link *dtype;
2081         
2082         FENTRY;
2083
2084         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2085         /* look for call */
2086         for (ic = lic ; ic ; ic = ic->next) 
2087                 if (ic->op == CALL || ic->op == PCALL)
2088                         break;
2089                 
2090                 if (!ic) {
2091                         fprintf(stderr,"found parameter push with no function call\n");
2092                         return ;
2093                 }
2094                 
2095                 /* if the registers have been saved already then
2096                 do nothing */
2097                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2098                         return ;
2099                 
2100                         /* find the registers in use at this time 
2101                 and push them away to safety */
2102                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2103                         ic->rUsed);
2104                 
2105                 ic->regsSaved = 1;
2106                 if (options.useXstack) {
2107                         if (bitVectBitValue(rsave,R0_IDX))
2108                                 pic14_emitcode("mov","b,r0");
2109                         pic14_emitcode("mov","r0,%s",spname);
2110                         for (i = 0 ; i < pic14_nRegs ; i++) {
2111                                 if (bitVectBitValue(rsave,i)) {
2112                                         if (i == R0_IDX)
2113                                                 pic14_emitcode("mov","a,b");
2114                                         else
2115                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2116                                         pic14_emitcode("movx","@r0,a");
2117                                         pic14_emitcode("inc","r0");
2118                                 }
2119                         }
2120                         pic14_emitcode("mov","%s,r0",spname);
2121                         if (bitVectBitValue(rsave,R0_IDX))
2122                                 pic14_emitcode("mov","r0,b");     
2123                 }// else
2124                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2125                 //        if (bitVectBitValue(rsave,i))
2126                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2127                 //}
2128                 
2129                 dtype = operandType(IC_LEFT(ic));
2130                 if (currFunc && dtype && 
2131                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2132                         IFFUNC_ISISR(currFunc->type) &&
2133                         !ic->bankSaved) 
2134                         
2135                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2136                 
2137 }
2138 /*-----------------------------------------------------------------*/
2139 /* unsaveRegisters - pop the pushed registers                                      */
2140 /*-----------------------------------------------------------------*/
2141 static void unsaveRegisters (iCode *ic)
2142 {
2143         int i;
2144         bitVect *rsave;
2145         
2146         FENTRY;
2147
2148         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2149         /* find the registers in use at this time 
2150         and push them away to safety */
2151         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2152                 ic->rUsed);
2153         
2154         if (options.useXstack) {
2155                 pic14_emitcode("mov","r0,%s",spname); 
2156                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2157                         if (bitVectBitValue(rsave,i)) {
2158                                 pic14_emitcode("dec","r0");
2159                                 pic14_emitcode("movx","a,@r0");
2160                                 if (i == R0_IDX)
2161                                         pic14_emitcode("mov","b,a");
2162                                 else
2163                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2164                         }       
2165                         
2166                 }
2167                 pic14_emitcode("mov","%s,r0",spname);
2168                 if (bitVectBitValue(rsave,R0_IDX))
2169                         pic14_emitcode("mov","r0,b");
2170         } //else
2171         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2172         //      if (bitVectBitValue(rsave,i))
2173         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2174         //}
2175         
2176 }  
2177
2178
2179 /*-----------------------------------------------------------------*/
2180 /* pushSide -                            */
2181 /*-----------------------------------------------------------------*/
2182 static void pushSide(operand * oper, int size)
2183 {
2184 #if 0
2185         int offset = 0;
2186         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2187         while (size--) {
2188                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2189                 if (AOP_TYPE(oper) != AOP_REG &&
2190                         AOP_TYPE(oper) != AOP_DIR &&
2191                         strcmp(l,"a") ) {
2192                         pic14_emitcode("mov","a,%s",l);
2193                         pic14_emitcode("push","acc");
2194                 } else
2195                         pic14_emitcode("push","%s",l);
2196         }
2197 #endif
2198 }
2199
2200 /*-----------------------------------------------------------------*/
2201 /* assignResultValue -                           */
2202 /*-----------------------------------------------------------------*/
2203 static void assignResultValue(operand * oper)
2204 {
2205         int size = AOP_SIZE(oper);
2206         
2207         FENTRY;
2208
2209         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2210         
2211         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2212         
2213         while (size--) {
2214                 if (GpsuedoStkPtr++)
2215                         emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2216                 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2217         }
2218 }
2219
2220
2221 /*-----------------------------------------------------------------*/
2222 /* genIpush - genrate code for pushing this gets a little complex  */
2223 /*-----------------------------------------------------------------*/
2224 static void genIpush (iCode *ic)
2225 {
2226         FENTRY;
2227         
2228         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2229 #if 0
2230         int size, offset = 0 ;
2231         char *l;
2232         
2233         
2234         /* if this is not a parm push : ie. it is spill push 
2235         and spill push is always done on the local stack */
2236         if (!ic->parmPush) {
2237                 
2238                 /* and the item is spilt then do nothing */
2239                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2240                         return ;
2241                 
2242                 aopOp(IC_LEFT(ic),ic,FALSE);
2243                 size = AOP_SIZE(IC_LEFT(ic));
2244                 /* push it on the stack */
2245                 while(size--) {
2246                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2247                         if (*l == '#') {
2248                                 MOVA(l);
2249                                 l = "acc";
2250                         }
2251                         pic14_emitcode("push","%s",l);
2252                 }
2253                 return ;                
2254         }
2255         
2256         /* this is a paramter push: in this case we call
2257         the routine to find the call and save those
2258         registers that need to be saved */   
2259         saveRegisters(ic);
2260         
2261         /* then do the push */
2262         aopOp(IC_LEFT(ic),ic,FALSE);
2263         
2264         
2265         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2266         size = AOP_SIZE(IC_LEFT(ic));
2267         
2268         while (size--) {
2269                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2270                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2271                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2272                         strcmp(l,"a") ) {
2273                         pic14_emitcode("mov","a,%s",l);
2274                         pic14_emitcode("push","acc");
2275                 } else
2276                         pic14_emitcode("push","%s",l);
2277         }         
2278         
2279         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2280 #endif
2281 }
2282
2283 /*-----------------------------------------------------------------*/
2284 /* genIpop - recover the registers: can happen only for spilling   */
2285 /*-----------------------------------------------------------------*/
2286 static void genIpop (iCode *ic)
2287 {
2288         FENTRY;
2289
2290         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2291 #if 0
2292         int size,offset ;
2293         
2294         
2295         /* if the temp was not pushed then */
2296         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2297                 return ;
2298         
2299         aopOp(IC_LEFT(ic),ic,FALSE);
2300         size = AOP_SIZE(IC_LEFT(ic));
2301         offset = (size-1);
2302         while (size--) 
2303                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2304                 FALSE,TRUE));
2305         
2306         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2307 #endif
2308 }
2309
2310 /*-----------------------------------------------------------------*/
2311 /* unsaverbank - restores the resgister bank from stack                    */
2312 /*-----------------------------------------------------------------*/
2313 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2314 {
2315         FENTRY;
2316
2317         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2318 #if 0
2319         int i;
2320         asmop *aop ;
2321         regs *r = NULL;
2322         
2323         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2324         if (popPsw) {
2325                 if (options.useXstack) {
2326                         aop = newAsmop(0);
2327                         r = getFreePtr(ic,&aop,FALSE);
2328                         
2329                         
2330                         pic14_emitcode("mov","%s,_spx",r->name);
2331                         pic14_emitcode("movx","a,@%s",r->name);
2332                         pic14_emitcode("mov","psw,a");
2333                         pic14_emitcode("dec","%s",r->name);
2334                         
2335                 }else
2336                         pic14_emitcode ("pop","psw");
2337         }
2338         
2339         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2340                 if (options.useXstack) {           
2341                         pic14_emitcode("movx","a,@%s",r->name);
2342                         //pic14_emitcode("mov","(%s+%d),a",
2343                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2344                         pic14_emitcode("dec","%s",r->name);
2345                         
2346                 } else 
2347                         pic14_emitcode("pop",""); //"(%s+%d)",
2348                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2349         }
2350         
2351         if (options.useXstack) {
2352                 
2353                 pic14_emitcode("mov","_spx,%s",r->name);
2354                 freeAsmop(NULL,aop,ic,TRUE);
2355                 
2356         }
2357 #endif 
2358 }
2359
2360 /*-----------------------------------------------------------------*/
2361 /* saverbank - saves an entire register bank on the stack                  */
2362 /*-----------------------------------------------------------------*/
2363 static void saverbank (int bank, iCode *ic, bool pushPsw)
2364 {
2365         FENTRY;
2366
2367         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2368 #if 0
2369         int i;
2370         asmop *aop ;
2371         regs *r = NULL;
2372         
2373         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2374         if (options.useXstack) {
2375                 
2376                 aop = newAsmop(0);
2377                 r = getFreePtr(ic,&aop,FALSE);  
2378                 pic14_emitcode("mov","%s,_spx",r->name);
2379                 
2380         }
2381         
2382         for (i = 0 ; i < pic14_nRegs ;i++) {
2383                 if (options.useXstack) {
2384                         pic14_emitcode("inc","%s",r->name);
2385                         //pic14_emitcode("mov","a,(%s+%d)",
2386                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2387                         pic14_emitcode("movx","@%s,a",r->name);                 
2388                 } else 
2389                         pic14_emitcode("push","");// "(%s+%d)",
2390                 //regspic14[i].base,8*bank+regspic14[i].offset);
2391         }
2392         
2393         if (pushPsw) {
2394                 if (options.useXstack) {
2395                         pic14_emitcode("mov","a,psw");
2396                         pic14_emitcode("movx","@%s,a",r->name); 
2397                         pic14_emitcode("inc","%s",r->name);
2398                         pic14_emitcode("mov","_spx,%s",r->name);                 
2399                         freeAsmop (NULL,aop,ic,TRUE);
2400                         
2401                 } else
2402                         pic14_emitcode("push","psw");
2403                 
2404                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2405         }
2406         ic->bankSaved = 1;
2407 #endif
2408 }
2409
2410 /*-----------------------------------------------------------------*/
2411 /* genCall - generates a call statement                                                    */
2412 /*-----------------------------------------------------------------*/
2413 static void genCall (iCode *ic)
2414 {
2415         sym_link *dtype;         
2416         symbol *sym;
2417         unsigned char *name;
2418         int isExtern;
2419         
2420         FENTRY;
2421
2422         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2423         
2424         /* if caller saves & we have not saved then */
2425         if (!ic->regsSaved)
2426                 saveRegisters(ic);
2427         
2428                 /* if we are calling a function that is not using
2429                 the same register bank then we need to save the
2430         destination registers on the stack */
2431         dtype = operandType(IC_LEFT(ic));
2432         if (currFunc && dtype && 
2433                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2434                 IFFUNC_ISISR(currFunc->type) &&
2435                 !ic->bankSaved) 
2436                 
2437                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2438         
2439         /* if send set is not empty the assign */
2440         if (_G.sendSet) {
2441                 iCode *sic;
2442                 /* For the Pic port, there is no data stack.
2443                 * So parameters passed to functions are stored
2444                 * in registers. (The pCode optimizer will get
2445                 * rid of most of these :).
2446                 */
2447                 int psuedoStkPtr=-1;
2448                 int firstTimeThruLoop = 1;
2449                 
2450                 _G.sendSet = reverseSet(_G.sendSet);
2451                 
2452                 /* First figure how many parameters are getting passed */
2453                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2454                 sic = setNextItem(_G.sendSet)) {
2455                         
2456                         aopOp(IC_LEFT(sic),sic,FALSE);
2457                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2458                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2459                 }
2460                 
2461                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2462                 sic = setNextItem(_G.sendSet)) {
2463                         int size, offset = 0;
2464                         
2465                         aopOp(IC_LEFT(sic),sic,FALSE);
2466                         size = AOP_SIZE(IC_LEFT(sic));
2467                         
2468                         while (size--) {
2469                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2470                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2471                                 
2472                                 if(!firstTimeThruLoop) {
2473                                         /* If this is not the first time we've been through the loop
2474                                         * then we need to save the parameter in a temporary
2475                                         * register. The last byte of the last parameter is
2476                                         * passed in W. */
2477                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2478                                         
2479                                 }
2480                                 firstTimeThruLoop=0;
2481                                 
2482                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2483                                 offset++;
2484                         }
2485                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2486                 }
2487                 _G.sendSet = NULL;
2488         }
2489         /* make the call */
2490         sym = OP_SYMBOL(IC_LEFT(ic));
2491         name = sym->rname[0] ? sym->rname : sym->name;
2492         isExtern = IS_EXTERN(sym->etype);
2493         if (isExtern) {
2494                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2495         }
2496         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2497         if (isExtern) {
2498                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2499         }
2500         GpsuedoStkPtr=0;
2501         /* if we need assign a result value */
2502         if ((IS_ITEMP(IC_RESULT(ic)) && 
2503                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2504                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2505                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2506                 
2507                 _G.accInUse++;
2508                 aopOp(IC_RESULT(ic),ic,FALSE);
2509                 _G.accInUse--;
2510                 
2511                 assignResultValue(IC_RESULT(ic));
2512                 
2513                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2514                         AopType(AOP_TYPE(IC_RESULT(ic))));
2515                 
2516                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2517         }
2518         
2519         /* adjust the stack for parameters if 
2520         required */
2521         if (ic->parmBytes) {
2522                 int i;
2523                 if (ic->parmBytes > 3) {
2524                         pic14_emitcode("mov","a,%s",spname);
2525                         pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2526                         pic14_emitcode("mov","%s,a",spname);
2527                 } else 
2528                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2529                                 pic14_emitcode("dec","%s",spname);
2530                         
2531         }
2532         
2533         /* if register bank was saved then pop them */
2534         if (ic->bankSaved)
2535                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2536         
2537         /* if we hade saved some registers then unsave them */
2538         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2539                 unsaveRegisters (ic);
2540         
2541         
2542 }
2543
2544 /*-----------------------------------------------------------------*/
2545 /* genPcall - generates a call by pointer statement                        */
2546 /*-----------------------------------------------------------------*/
2547 static void genPcall (iCode *ic)
2548 {
2549         sym_link *dtype;
2550         symbol *albl = newiTempLabel(NULL);
2551         symbol *blbl = newiTempLabel(NULL);
2552         PIC_OPCODE poc;
2553         pCodeOp *pcop;
2554         operand *left;
2555         
2556         FENTRY;
2557
2558         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2559         /* if caller saves & we have not saved then */
2560         if (!ic->regsSaved)
2561                 saveRegisters(ic);
2562         
2563                 /* if we are calling a function that is not using
2564                 the same register bank then we need to save the
2565         destination registers on the stack */
2566         dtype = operandType(IC_LEFT(ic));
2567         if (currFunc && dtype && 
2568                 IFFUNC_ISISR(currFunc->type) &&
2569                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2570                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2571         
2572         left = IC_LEFT(ic);
2573         aopOp(left,ic,FALSE);
2574         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2575         
2576         pushSide(IC_LEFT(ic), FPTRSIZE);
2577         
2578         /* if send set is not empty, assign parameters */
2579         if (_G.sendSet) {
2580                 
2581                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2582                 /* no way to pass args - W always gets used to make the call */
2583         }
2584         /* first idea - factor out a common helper function and call it.
2585         But don't know how to get it generated only once in its own block
2586         
2587         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2588                 char *rname;
2589                 char *buffer;
2590                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2591                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2592                 buffer = Safe_calloc(1,strlen(rname)+16);
2593                 sprintf(buffer, "%s_goto_helper", rname);
2594                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2595                 free(buffer);
2596         }
2597         */
2598         emitpcode(POC_CALL,popGetLabel(albl->key));
2599         pcop = popGetLabel(blbl->key);
2600         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2601         emitpcode(POC_GOTO,pcop);
2602         emitpLabel(albl->key);
2603         
2604         poc = ( aop_isLitLike (AOP(left)) ? POC_MOVLW : POC_MOVFW );
2605         
2606         emitpcode(poc,popGetAddr(AOP(left),1,0));
2607         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2608         emitpcode(poc,popGetAddr(AOP(left),0,0));
2609         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2610         
2611         emitpLabel(blbl->key);
2612         
2613         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2614         
2615         /* if we need to assign a result value */
2616         if ((IS_ITEMP(IC_RESULT(ic)) &&
2617                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2618                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2619                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2620                 
2621                 _G.accInUse++;
2622                 aopOp(IC_RESULT(ic),ic,FALSE);
2623                 _G.accInUse--;
2624                 
2625                 assignResultValue(IC_RESULT(ic));
2626                 
2627                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2628         }
2629         
2630         /* if register bank was saved then unsave them */
2631         if (currFunc && dtype && 
2632                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2633                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2634         
2635                 /* if we hade saved some registers then
2636         unsave them */
2637         if (ic->regsSaved)
2638                 unsaveRegisters (ic);
2639         
2640 }
2641
2642 /*-----------------------------------------------------------------*/
2643 /* resultRemat - result  is rematerializable                                       */
2644 /*-----------------------------------------------------------------*/
2645 static int resultRemat (iCode *ic)
2646 {
2647         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2648         FENTRY;
2649
2650         if (SKIP_IC(ic) || ic->op == IFX)
2651                 return 0;
2652         
2653         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2654                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2655                 if (sym->remat && !POINTER_SET(ic)) 
2656                         return 1;
2657         }
2658         
2659         return 0;
2660 }
2661
2662 #if defined(__BORLANDC__) || defined(_MSC_VER)
2663 #define STRCASECMP stricmp
2664 #else
2665 #define STRCASECMP strcasecmp
2666 #endif
2667
2668 #if 0
2669 /*-----------------------------------------------------------------*/
2670 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2671 /*-----------------------------------------------------------------*/
2672 static bool inExcludeList(char *s)
2673 {
2674         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2675         int i =0;
2676         
2677         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2678         if (options.excludeRegs[i] &&
2679                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2680                 return FALSE ;
2681         
2682         for ( i = 0 ; options.excludeRegs[i]; i++) {
2683                 if (options.excludeRegs[i] &&
2684                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2685                         return TRUE;
2686         }
2687         return FALSE ;
2688 }
2689 #endif
2690
2691 /*-----------------------------------------------------------------*/
2692 /* genFunction - generated code for function entry                                 */
2693 /*-----------------------------------------------------------------*/
2694 static void genFunction (iCode *ic)
2695 {
2696         symbol *sym;
2697         sym_link *ftype;
2698         
2699         FENTRY;
2700
2701         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2702         
2703         labelOffset += (max_key+4);
2704         max_key=0;
2705         GpsuedoStkPtr=0;
2706         _G.nRegsSaved = 0;
2707         /* create the function header */
2708         pic14_emitcode(";","-----------------------------------------");
2709         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2710         pic14_emitcode(";","-----------------------------------------");
2711         
2712         pic14_emitcode("","%s:",sym->rname);
2713         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2714         
2715         ftype = operandType(IC_LEFT(ic));
2716         
2717         /* if critical function then turn interrupts off */
2718         if (IFFUNC_ISCRITICAL(ftype))
2719                 pic14_emitcode("clr","ea");
2720         
2721                 /* here we need to generate the equates for the
2722         register bank if required */
2723 #if 0
2724         if (FUNC_REGBANK(ftype) != rbank) {
2725                 int i ;
2726                 
2727                 rbank = FUNC_REGBANK(ftype);
2728                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2729                         if (strcmp(regspic14[i].base,"0") == 0)
2730                                 pic14_emitcode("","%s = 0x%02x",
2731                                 regspic14[i].dname,
2732                                 8*rbank+regspic14[i].offset);
2733                         else
2734                                 pic14_emitcode ("","%s = %s + 0x%02x",
2735                                 regspic14[i].dname,
2736                                 regspic14[i].base,
2737                                 8*rbank+regspic14[i].offset);
2738                 }
2739         }
2740 #endif
2741         
2742         /* if this is an interrupt service routine */
2743         if (IFFUNC_ISISR(sym->type)) {
2744         /*  already done in pic14createInterruptVect() - delete me
2745         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2746         emitpcodeNULLop(POC_NOP);
2747         emitpcodeNULLop(POC_NOP);
2748         emitpcodeNULLop(POC_NOP);
2749                 */
2750                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2751                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2752                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2753                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2754                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2755                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2756                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2757                 
2758                 pBlockConvert2ISR(pb);
2759 #if 0  
2760                 if (!inExcludeList("acc"))              
2761                         pic14_emitcode ("push","acc");  
2762                 if (!inExcludeList("b"))
2763                         pic14_emitcode ("push","b");
2764                 if (!inExcludeList("dpl"))
2765                         pic14_emitcode ("push","dpl");
2766                 if (!inExcludeList("dph"))
2767                         pic14_emitcode ("push","dph");
2768                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2769                 {
2770                         pic14_emitcode ("push", "dpx");
2771                         /* Make sure we're using standard DPTR */
2772                         pic14_emitcode ("push", "dps");
2773                         pic14_emitcode ("mov", "dps, #0x00");
2774                         if (options.stack10bit)
2775                         { 
2776                                 /* This ISR could conceivably use DPTR2. Better save it. */
2777                                 pic14_emitcode ("push", "dpl1");
2778                                 pic14_emitcode ("push", "dph1");
2779                                 pic14_emitcode ("push", "dpx1");
2780                         }
2781                 }
2782                 /* if this isr has no bank i.e. is going to
2783                 run with bank 0 , then we need to save more
2784                 registers :-) */
2785                 if (!FUNC_REGBANK(sym->type)) {
2786                         
2787                 /* if this function does not call any other
2788                 function then we can be economical and
2789                         save only those registers that are used */
2790                         if (! IFFUNC_HASFCALL(sym->type)) {
2791                                 int i;
2792                                 
2793                                 /* if any registers used */
2794                                 if (sym->regsUsed) {
2795                                         /* save the registers used */
2796                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2797                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2798                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2799                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2800                                         }
2801                                 }
2802                                 
2803                         } else {
2804                         /* this function has    a function call cannot
2805                         determines register usage so we will have the
2806                                 entire bank */
2807                                 saverbank(0,ic,FALSE);
2808                         }       
2809                 }
2810 #endif
2811         } else {
2812         /* if callee-save to be used for this function
2813                 then save the registers being used in this function */
2814                 if (IFFUNC_CALLEESAVES(sym->type)) {
2815                         int i;
2816                         
2817                         /* if any registers used */
2818                         if (sym->regsUsed) {
2819                                 /* save the registers used */
2820                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2821                                         if (bitVectBitValue(sym->regsUsed,i) ||
2822                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2823                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2824                                                 _G.nRegsSaved++;
2825                                         }
2826                                 }
2827                         }
2828                 }
2829         }
2830         
2831         /* set the register bank to the desired value */
2832         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2833                 pic14_emitcode("push","psw");
2834                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
2835         }
2836         
2837         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2838                 
2839                 if (options.useXstack) {
2840                         pic14_emitcode("mov","r0,%s",spname);
2841                         pic14_emitcode("mov","a,_bp");
2842                         pic14_emitcode("movx","@r0,a");
2843                         pic14_emitcode("inc","%s",spname);
2844                 }
2845                 else
2846                 {
2847                         /* set up the stack */
2848                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
2849                 }
2850                 pic14_emitcode ("mov","_bp,%s",spname);
2851         }
2852         
2853         /* adjust the stack for the function */
2854         if (sym->stack) {
2855                 
2856                 int i = sym->stack;
2857                 if (i > 256 ) 
2858                         werror(W_STACK_OVERFLOW,sym->name);
2859                 
2860                 if (i > 3 && sym->recvSize < 4) {                
2861                         
2862                         pic14_emitcode ("mov","a,sp");
2863                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2864                         pic14_emitcode ("mov","sp,a");
2865                         
2866                 }
2867                 else
2868                         while(i--)
2869                                 pic14_emitcode("inc","sp");
2870         }
2871         
2872         if (sym->xstack) {
2873                 
2874                 pic14_emitcode ("mov","a,_spx");
2875                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2876                 pic14_emitcode ("mov","_spx,a");
2877         }
2878         
2879 }
2880
2881 /*-----------------------------------------------------------------*/
2882 /* genEndFunction - generates epilogue for functions                       */
2883 /*-----------------------------------------------------------------*/
2884 static void genEndFunction (iCode *ic)
2885 {
2886         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2887         
2888         FENTRY;
2889
2890         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2891         
2892         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2893         {
2894                 pic14_emitcode ("mov","%s,_bp",spname);
2895         }
2896         
2897         /* if use external stack but some variables were
2898         added to the local stack then decrement the
2899         local stack */
2900         if (options.useXstack && sym->stack) {    
2901                 pic14_emitcode("mov","a,sp");
2902                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2903                 pic14_emitcode("mov","sp,a");
2904         }
2905         
2906         
2907         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2908                 if (options.useXstack) {
2909                         pic14_emitcode("mov","r0,%s",spname);
2910                         pic14_emitcode("movx","a,@r0");
2911                         pic14_emitcode("mov","_bp,a");
2912                         pic14_emitcode("dec","%s",spname);
2913                 }
2914                 else
2915                 {
2916                         pic14_emitcode ("pop","_bp");
2917                 }
2918         }
2919         
2920         /* restore the register bank    */        
2921         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2922                 pic14_emitcode ("pop","psw");
2923         
2924         if (IFFUNC_ISISR(sym->type)) {
2925                 
2926                 /* now we need to restore the registers */
2927                 /* if this isr has no bank i.e. is going to
2928                 run with bank 0 , then we need to save more
2929 registers :-) */
2930                 if (!FUNC_REGBANK(sym->type)) {
2931                         
2932                 /* if this function does not call any other
2933                 function then we can be economical and
2934                         save only those registers that are used */
2935                         if (! IFFUNC_HASFCALL(sym->type)) {
2936                                 int i;
2937                                 
2938                                 /* if any registers used */
2939                                 if (sym->regsUsed) {
2940                                         /* save the registers used */
2941                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2942                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2943                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2944                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2945                                         }
2946                                 }
2947                                 
2948                         } else {
2949                         /* this function has    a function call cannot
2950                         determines register usage so we will have the
2951                                 entire bank */
2952                                 unsaverbank(0,ic,FALSE);
2953                         }       
2954                 }
2955 #if 0
2956                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2957                 {
2958                         if (options.stack10bit)
2959                         {
2960                                 pic14_emitcode ("pop", "dpx1");
2961                                 pic14_emitcode ("pop", "dph1");
2962                                 pic14_emitcode ("pop", "dpl1");
2963                         } 
2964                         pic14_emitcode ("pop", "dps");
2965                         pic14_emitcode ("pop", "dpx");
2966                 }
2967                 if (!inExcludeList("dph"))
2968                         pic14_emitcode ("pop","dph");
2969                 if (!inExcludeList("dpl"))
2970                         pic14_emitcode ("pop","dpl");
2971                 if (!inExcludeList("b"))
2972                         pic14_emitcode ("pop","b");
2973                 if (!inExcludeList("acc"))
2974                         pic14_emitcode ("pop","acc");
2975                 
2976                 if (IFFUNC_ISCRITICAL(sym->type))
2977                         pic14_emitcode("setb","ea");
2978 #endif
2979                 
2980                 /* if debug then send end of function */
2981                 /*      if (options.debug && currFunc) { */
2982                 if (currFunc) {
2983                         debugFile->writeEndFunction (currFunc, ic, 1);
2984                 }
2985                 
2986                 pic14_emitcode ("reti","");
2987                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2988                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2989                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2990                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2991                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2992                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2993                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2994                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
2995                 emitpcodeNULLop(POC_RETFIE);
2996         }
2997         else {
2998                 if (IFFUNC_ISCRITICAL(sym->type))
2999                         pic14_emitcode("setb","ea");
3000                 
3001                 if (IFFUNC_CALLEESAVES(sym->type)) {
3002                         int i;
3003                         
3004                         /* if any registers used */
3005                         if (sym->regsUsed) {
3006                                 /* save the registers used */
3007                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3008                                         if (bitVectBitValue(sym->regsUsed,i) ||
3009                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3010                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3011                                 }
3012                         }
3013                         
3014                 }
3015                 
3016                 /* if debug then send end of function */
3017                 if (currFunc) {
3018                         debugFile->writeEndFunction (currFunc, ic, 1);
3019                 }
3020                 
3021                 pic14_emitcode ("return","");
3022                 emitpcodeNULLop(POC_RETURN);
3023                 
3024                 /* Mark the end of a function */
3025                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3026         }
3027         
3028 }
3029
3030 /*-----------------------------------------------------------------*/
3031 /* genRet - generate code for return statement                                     */
3032 /*-----------------------------------------------------------------*/
3033 static void genRet (iCode *ic)
3034 {
3035         int size,offset = 0 , pushed = 0;
3036         
3037         FENTRY;
3038
3039         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3040         /* if we have no return value then
3041         just generate the "ret" */
3042         if (!IC_LEFT(ic)) 
3043                 goto jumpret;           
3044         
3045                 /* we have something to return then
3046         move the return value into place */
3047         aopOp(IC_LEFT(ic),ic,FALSE);
3048         size = AOP_SIZE(IC_LEFT(ic));
3049         
3050         while (size--) {
3051                 char *l ;
3052                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3053                         /* #NOCHANGE */
3054                         l = aopGet(AOP(IC_LEFT(ic)),offset++,
3055                                 FALSE,TRUE);
3056                         pic14_emitcode("push","%s",l);
3057                         pushed++;
3058                 } else {
3059                         l = aopGet(AOP(IC_LEFT(ic)),offset,
3060                                 FALSE,FALSE);
3061                         if (strcmp(fReturn[offset],l)) {
3062                                 if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
3063                                         AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
3064                                         ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3065                                         ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3066                                         emitpcode(POC_MOVLW, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
3067                                 }else {
3068                                         emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3069                                 }
3070                                 if(size) {
3071                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
3072                                 }
3073                                 offset++;
3074                         }
3075                 }
3076         }
3077         
3078         if (pushed) {
3079                 while(pushed) {
3080                         pushed--;
3081                         if (strcmp(fReturn[pushed],"a"))
3082                                 pic14_emitcode("pop",fReturn[pushed]);
3083                         else
3084                                 pic14_emitcode("pop","acc");
3085                 }
3086         }
3087         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3088         
3089 jumpret:
3090         /* generate a jump to the return label
3091         if the next is not the return statement */
3092         if (!(ic->next && ic->next->op == LABEL &&
3093                 IC_LABEL(ic->next) == returnLabel)) {
3094                 
3095                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3096                 pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3097         }
3098         
3099 }
3100
3101 /*-----------------------------------------------------------------*/
3102 /* genLabel - generates a label                                                                    */
3103 /*-----------------------------------------------------------------*/
3104 static void genLabel (iCode *ic)
3105 {
3106         FENTRY;
3107
3108         /* special case never generate */
3109         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3110         if (IC_LABEL(ic) == entryLabel)
3111                 return ;
3112         
3113         emitpLabel(IC_LABEL(ic)->key);
3114         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3115 }
3116
3117 /*-----------------------------------------------------------------*/
3118 /* genGoto - generates a goto                                                                      */
3119 /*-----------------------------------------------------------------*/
3120 //tsd
3121 static void genGoto (iCode *ic)
3122 {
3123         FENTRY;
3124
3125         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3126         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3127 }
3128
3129
3130 /*-----------------------------------------------------------------*/
3131 /* genMultbits :- multiplication of bits                                                   */
3132 /*-----------------------------------------------------------------*/
3133 static void genMultbits (operand *left, 
3134                                                  operand *right, 
3135                                                  operand *result)
3136 {
3137         FENTRY;
3138         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3139         
3140         if(!pic14_sameRegs(AOP(result),AOP(right)))
3141                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3142         
3143         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3144         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3145         emitpcode(POC_BCF,  popGet(AOP(result),0));
3146         
3147 }
3148
3149
3150 /*-----------------------------------------------------------------*/
3151 /* genMultOneByte : 8 bit multiplication & division                        */
3152 /*-----------------------------------------------------------------*/
3153 static void genMultOneByte (operand *left,
3154                                                         operand *right,
3155                                                         operand *result)
3156 {
3157         sym_link *opetype = operandType(result);
3158         
3159         // symbol *lbl ;
3160         int size,offset;
3161         
3162         FENTRY;
3163         
3164         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3165         DEBUGpic14_AopType(__LINE__,left,right,result);
3166         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3167         
3168         /* (if two literals, the value is computed before) */
3169         /* if one literal, literal on the right */
3170         if (AOP_TYPE(left) == AOP_LIT){
3171                 operand *t = right;
3172                 right = left;
3173                 left = t;
3174         }
3175         
3176         size = AOP_SIZE(result);
3177         if(size == 1) {
3178                 
3179                 if (AOP_TYPE(right) == AOP_LIT){
3180                         pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3181                                 aopGet(AOP(right),0,FALSE,FALSE), 
3182                                 aopGet(AOP(left),0,FALSE,FALSE), 
3183                                 aopGet(AOP(result),0,FALSE,FALSE));
3184                         pic14_emitcode("call","genMultLit");
3185                 } else {
3186                         pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3187                                 aopGet(AOP(right),0,FALSE,FALSE), 
3188                                 aopGet(AOP(left),0,FALSE,FALSE), 
3189                                 aopGet(AOP(result),0,FALSE,FALSE));
3190                         pic14_emitcode("call","genMult8X8_8");
3191                         
3192                 }
3193                 genMult8X8_8 (left, right,result);
3194                 
3195                 
3196                 /* signed or unsigned */
3197                 //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3198                 //l = aopGet(AOP(left),0,FALSE,FALSE);
3199                 //MOVA(l);               
3200                 //pic14_emitcode("mul","ab");
3201                 /* if result size = 1, mul signed = mul unsigned */
3202                 //aopPut(AOP(result),"a",0);
3203                 
3204         } else {        // (size > 1)
3205                 
3206                 pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3207                         aopGet(AOP(right),0,FALSE,FALSE), 
3208                         aopGet(AOP(left),0,FALSE,FALSE), 
3209                         aopGet(AOP(result),0,FALSE,FALSE));
3210                 
3211                 if (SPEC_USIGN(opetype)){
3212                         pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3213                         genUMult8X8_16 (left, right, result, NULL);
3214                         
3215                         if (size > 2) {
3216                                 /* for filling the MSBs */
3217                                 emitpcode(POC_CLRF,  popGet(AOP(result),2));
3218                                 emitpcode(POC_CLRF,  popGet(AOP(result),3));
3219                         }
3220                 }
3221                 else{
3222                         pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3223                         
3224                         pic14_emitcode("mov","a,b");
3225                         
3226                         /* adjust the MSB if left or right neg */
3227                         
3228                         /* if one literal */
3229                         if (AOP_TYPE(right) == AOP_LIT){
3230                                 pic14_emitcode("multiply ","right is a lit");
3231                                 /* AND literal negative */
3232                                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3233                                         /* adjust MSB (c==0 after mul) */
3234                                         pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3235                                 }
3236                         }
3237                         else{
3238                                 genSMult8X8_16 (left, right, result, NULL);
3239                         }
3240                         
3241                         if(size > 2){
3242                                 pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3243                                 /* get the sign */
3244                                 pic14_emitcode("rlc","a");
3245                                 pic14_emitcode("subb","a,acc");
3246                         }
3247                 }
3248                 
3249                 size -= 2;
3250                 offset = 2;
3251                 if (size > 0)
3252                         while (size--)
3253                                 pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3254                         //aopPut(AOP(result),"a",offset++);
3255         }
3256 }
3257
3258 /*-----------------------------------------------------------------*/
3259 /* genMult - generates code for multiplication                                     */
3260 /*-----------------------------------------------------------------*/
3261 static void genMult (iCode *ic)
3262 {
3263         operand *left = IC_LEFT(ic);
3264         operand *right = IC_RIGHT(ic);
3265         operand *result= IC_RESULT(ic); 
3266         
3267         FENTRY;
3268
3269         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3270         /* assign the amsops */
3271         aopOp (left,ic,FALSE);
3272         aopOp (right,ic,FALSE);
3273         aopOp (result,ic,TRUE);
3274         
3275         DEBUGpic14_AopType(__LINE__,left,right,result);
3276         
3277         /* special cases first */
3278         /* both are bits */
3279         if (AOP_TYPE(left) == AOP_CRY &&
3280                 AOP_TYPE(right)== AOP_CRY) {
3281                 genMultbits(left,right,result);
3282                 goto release ;
3283         }
3284         
3285         /* if both are of size == 1 */
3286         if (AOP_SIZE(left) == 1 &&
3287                 AOP_SIZE(right) == 1 ) {
3288                 genMultOneByte(left,right,result);
3289                 goto release ;
3290         }
3291         
3292         pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3293         
3294         /* should have been converted to function call */
3295         //assert(0) ;
3296         
3297 release :
3298         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3299         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3300         freeAsmop(result,NULL,ic,TRUE); 
3301 }
3302
3303 /*-----------------------------------------------------------------*/
3304 /* genDivbits :- division of bits                                                                  */
3305 /*-----------------------------------------------------------------*/
3306 static void genDivbits (operand *left, 
3307                                                 operand *right, 
3308                                                 operand *result)
3309 {
3310         
3311         char *l;
3312         
3313         FENTRY;
3314
3315         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3316         /* the result must be bit */      
3317         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3318         l = aopGet(AOP(left),0,FALSE,FALSE);
3319         
3320         MOVA(l);          
3321         
3322         pic14_emitcode("div","ab");
3323         pic14_emitcode("rrc","a");
3324         aopPut(AOP(result),"c",0);
3325 }
3326
3327 /*-----------------------------------------------------------------*/
3328 /* genDivOneByte : 8 bit division                                                                  */
3329 /*-----------------------------------------------------------------*/
3330 static void genDivOneByte (operand *left,
3331                                                    operand *right,
3332                                                    operand *result)
3333 {
3334         sym_link *opetype = operandType(result);
3335         char *l ;
3336         symbol *lbl ;
3337         int size,offset;
3338         
3339         FENTRY;
3340         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3341         size = AOP_SIZE(result) - 1;
3342         offset = 1;
3343         /* signed or unsigned */
3344         if (SPEC_USIGN(opetype)) {
3345                 /* unsigned is easy */
3346                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3347                 l = aopGet(AOP(left),0,FALSE,FALSE);
3348                 MOVA(l);                
3349                 pic14_emitcode("div","ab");
3350                 aopPut(AOP(result),"a",0);
3351                 while (size--)
3352                         aopPut(AOP(result),zero,offset++);
3353                 return ;
3354         }
3355         
3356         /* signed is a little bit more difficult */
3357         
3358         /* save the signs of the operands */
3359         l = aopGet(AOP(left),0,FALSE,FALSE);      
3360         MOVA(l);          
3361         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3362         pic14_emitcode("push","acc"); /* save it on the stack */
3363         
3364         /* now sign adjust for both left & right */
3365         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3366         MOVA(l);                 
3367         lbl = newiTempLabel(NULL);
3368         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3369         pic14_emitcode("cpl","a");   
3370         pic14_emitcode("inc","a");
3371         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3372         pic14_emitcode("mov","b,a");
3373         
3374         /* sign adjust left side */
3375         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3376         MOVA(l);
3377         
3378         lbl = newiTempLabel(NULL);
3379         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3380         pic14_emitcode("cpl","a");
3381         pic14_emitcode("inc","a");
3382         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3383         
3384         /* now the division */
3385         pic14_emitcode("div","ab");
3386         /* we are interested in the lower order
3387         only */
3388         pic14_emitcode("mov","b,a");
3389         lbl = newiTempLabel(NULL);
3390         pic14_emitcode("pop","acc");     
3391         /* if there was an over flow we don't 
3392         adjust the sign of the result */
3393         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3394         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3395         CLRC;
3396         pic14_emitcode("clr","a");
3397         pic14_emitcode("subb","a,b");
3398         pic14_emitcode("mov","b,a");
3399         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3400         
3401         /* now we are done */
3402         aopPut(AOP(result),"b",0);
3403         if(size > 0){
3404                 pic14_emitcode("mov","c,b.7");
3405                 pic14_emitcode("subb","a,acc");   
3406         }
3407         while (size--)
3408                 aopPut(AOP(result),"a",offset++);
3409         
3410 }
3411
3412 /*-----------------------------------------------------------------*/
3413 /* genDiv - generates code for division                                                    */
3414 /*-----------------------------------------------------------------*/
3415 static void genDiv (iCode *ic)
3416 {
3417         operand *left = IC_LEFT(ic);
3418         operand *right = IC_RIGHT(ic);
3419         operand *result= IC_RESULT(ic); 
3420         
3421         FENTRY;
3422         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3423         /* assign the amsops */
3424         aopOp (left,ic,FALSE);
3425         aopOp (right,ic,FALSE);
3426         aopOp (result,ic,TRUE);
3427         
3428         /* special cases first */
3429         /* both are bits */
3430         if (AOP_TYPE(left) == AOP_CRY &&
3431                 AOP_TYPE(right)== AOP_CRY) {
3432                 genDivbits(left,right,result);
3433                 goto release ;
3434         }
3435         
3436         /* if both are of size == 1 */
3437         if (AOP_SIZE(left) == 1 &&
3438                 AOP_SIZE(right) == 1 ) {
3439                 genDivOneByte(left,right,result);
3440                 goto release ;
3441         }
3442         
3443         /* should have been converted to function call */
3444         assert(0);
3445 release :
3446         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3447         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3448         freeAsmop(result,NULL,ic,TRUE); 
3449 }
3450
3451 /*-----------------------------------------------------------------*/
3452 /* genModbits :- modulus of bits                                                                   */
3453 /*-----------------------------------------------------------------*/
3454 static void genModbits (operand *left, 
3455                                                 operand *right, 
3456                                                 operand *result)
3457 {
3458         
3459         char *l;
3460         
3461         FENTRY;
3462         /* the result must be bit */      
3463         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3464         l = aopGet(AOP(left),0,FALSE,FALSE);
3465         
3466         MOVA(l);
3467         
3468         pic14_emitcode("div","ab");
3469         pic14_emitcode("mov","a,b");
3470         pic14_emitcode("rrc","a");
3471         aopPut(AOP(result),"c",0);
3472 }
3473
3474 /*-----------------------------------------------------------------*/
3475 /* genModOneByte : 8 bit modulus                                                                   */
3476 /*-----------------------------------------------------------------*/
3477 static void genModOneByte (operand *left,
3478                                                    operand *right,
3479                                                    operand *result)
3480 {
3481         sym_link *opetype = operandType(result);
3482         char *l ;
3483         symbol *lbl ;
3484         
3485         FENTRY;
3486         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3487         /* signed or unsigned */
3488         if (SPEC_USIGN(opetype)) {
3489                 /* unsigned is easy */
3490                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3491                 l = aopGet(AOP(left),0,FALSE,FALSE);
3492                 MOVA(l);        
3493                 pic14_emitcode("div","ab");
3494                 aopPut(AOP(result),"b",0);
3495                 return ;
3496         }
3497         
3498         /* signed is a little bit more difficult */
3499         
3500         /* save the signs of the operands */
3501         l = aopGet(AOP(left),0,FALSE,FALSE);      
3502         MOVA(l);
3503         
3504         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3505         pic14_emitcode("push","acc"); /* save it on the stack */
3506         
3507         /* now sign adjust for both left & right */
3508         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3509         MOVA(l);
3510         
3511         lbl = newiTempLabel(NULL);
3512         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3513         pic14_emitcode("cpl","a");   
3514         pic14_emitcode("inc","a");
3515         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3516         pic14_emitcode("mov","b,a"); 
3517         
3518         /* sign adjust left side */
3519         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3520         MOVA(l);
3521         
3522         lbl = newiTempLabel(NULL);
3523         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3524         pic14_emitcode("cpl","a");   
3525         pic14_emitcode("inc","a");
3526         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3527         
3528         /* now the multiplication */
3529         pic14_emitcode("div","ab");
3530         /* we are interested in the lower order
3531         only */
3532         lbl = newiTempLabel(NULL);
3533         pic14_emitcode("pop","acc");     
3534         /* if there was an over flow we don't 
3535         adjust the sign of the result */
3536         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3537         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3538         CLRC ;
3539         pic14_emitcode("clr","a");
3540         pic14_emitcode("subb","a,b");
3541         pic14_emitcode("mov","b,a");
3542         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3543         
3544         /* now we are done */
3545         aopPut(AOP(result),"b",0);
3546         
3547 }
3548
3549 /*-----------------------------------------------------------------*/
3550 /* genMod - generates code for division                                                    */
3551 /*-----------------------------------------------------------------*/
3552 static void genMod (iCode *ic)
3553 {
3554         operand *left = IC_LEFT(ic);
3555         operand *right = IC_RIGHT(ic);
3556         operand *result= IC_RESULT(ic);  
3557         
3558         FENTRY;
3559         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3560         /* assign the amsops */
3561         aopOp (left,ic,FALSE);
3562         aopOp (right,ic,FALSE);
3563         aopOp (result,ic,TRUE);
3564         
3565         /* special cases first */
3566         /* both are bits */
3567         if (AOP_TYPE(left) == AOP_CRY &&
3568                 AOP_TYPE(right)== AOP_CRY) {
3569                 genModbits(left,right,result);
3570                 goto release ;
3571         }
3572         
3573         /* if both are of size == 1 */
3574         if (AOP_SIZE(left) == 1 &&
3575                 AOP_SIZE(right) == 1 ) {
3576                 genModOneByte(left,right,result);
3577                 goto release ;
3578         }
3579         
3580         /* should have been converted to function call */
3581         assert(0);
3582         
3583 release :
3584         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3585         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3586         freeAsmop(result,NULL,ic,TRUE); 
3587 }
3588
3589 /*-----------------------------------------------------------------*/
3590 /* genIfxJump :- will create a jump depending on the ifx                   */
3591 /*-----------------------------------------------------------------*/
3592 /*
3593 note: May need to add parameter to indicate when a variable is in bit space.
3594 */
3595 static void genIfxJump (iCode *ic, char *jval)
3596 {
3597         
3598         FENTRY;
3599         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3600         /* if true label then we jump if condition
3601         supplied is true */
3602         if ( IC_TRUE(ic) ) {
3603                 
3604                 if(strcmp(jval,"a") == 0)
3605                         emitSKPZ;
3606                 else if (strcmp(jval,"c") == 0)
3607                         emitSKPC;
3608                 else {
3609                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3610                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3611                 }
3612                 
3613                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3614                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3615                 
3616         }
3617         else {
3618                 /* false label is present */
3619                 if(strcmp(jval,"a") == 0)
3620                         emitSKPNZ;
3621                 else if (strcmp(jval,"c") == 0)
3622                         emitSKPNC;
3623                 else {
3624                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3625                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3626                 }
3627                 
3628                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3629                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3630                 
3631         }
3632         
3633         
3634         /* mark the icode as generated */
3635         ic->generated = 1;
3636 }
3637
3638 /*-----------------------------------------------------------------*/
3639 /* genSkip                                                                                                                 */
3640 /*-----------------------------------------------------------------*/
3641 static void genSkip(iCode *ifx,int status_bit)
3642 {
3643         FENTRY;
3644         if(!ifx)
3645                 return;
3646         
3647         if ( IC_TRUE(ifx) ) {
3648                 switch(status_bit) {
3649                 case 'z':
3650                         emitSKPNZ;
3651                         break;
3652                         
3653                 case 'c':
3654                         emitSKPNC;
3655                         break;
3656                         
3657                 case 'd':
3658                         emitSKPDC;
3659                         break;
3660                         
3661                 }
3662                 
3663                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3664                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3665                 
3666         } else {
3667                 
3668                 switch(status_bit) {
3669                         
3670                 case 'z':
3671                         emitSKPZ;
3672                         break;
3673                         
3674                 case 'c':
3675                         emitSKPC;
3676                         break;
3677                         
3678                 case 'd':
3679                         emitSKPDC;
3680                         break;
3681                 }
3682                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3683                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3684                 
3685         }
3686         
3687 }
3688
3689 /*-----------------------------------------------------------------*/
3690 /* genSkipc                                                                                                        */
3691 /*-----------------------------------------------------------------*/
3692 static void genSkipc(resolvedIfx *rifx)
3693 {
3694         FENTRY;
3695         if(!rifx)
3696                 return;
3697         
3698         if(rifx->condition)
3699                 emitSKPC;
3700         else
3701                 emitSKPNC;
3702         
3703         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3704         rifx->generated = 1;
3705 }
3706
3707 /*-----------------------------------------------------------------*/
3708 /* genSkipz2                                                                                                       */
3709 /*-----------------------------------------------------------------*/
3710 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3711 {
3712         FENTRY;
3713         if(!rifx)
3714                 return;
3715         
3716         if( (rifx->condition ^ invert_condition) & 1)
3717                 emitSKPZ;
3718         else
3719                 emitSKPNZ;
3720         
3721         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3722         rifx->generated = 1;
3723 }
3724
3725 /*-----------------------------------------------------------------*/
3726 /* genSkipz                                                        */
3727 /*-----------------------------------------------------------------*/
3728 static void genSkipz(iCode *ifx, int condition)
3729 {
3730         FENTRY;
3731         if(!ifx)
3732                 return;
3733         
3734         if(condition)
3735                 emitSKPNZ;
3736         else
3737                 emitSKPZ;
3738         
3739         if ( IC_TRUE(ifx) )
3740                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3741         else
3742                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3743         
3744         if ( IC_TRUE(ifx) )
3745                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3746         else
3747                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3748         
3749 }
3750 /*-----------------------------------------------------------------*/
3751 /* genSkipCond                                                     */
3752 /*-----------------------------------------------------------------*/
3753 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3754 {
3755         FENTRY;
3756         if(!rifx)
3757                 return;
3758         
3759         if(rifx->condition)
3760                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3761         else
3762                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3763         
3764         
3765         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3766         rifx->generated = 1;
3767 }
3768
3769 #if 0
3770 /*-----------------------------------------------------------------*/
3771 /* genChkZeroes :- greater or less than comparison                 */
3772 /*     For each byte in a literal that is zero, inclusive or the   */
3773 /*     the corresponding byte in the operand with W                */
3774 /*     returns true if any of the bytes are zero                   */
3775 /*-----------------------------------------------------------------*/
3776 static int genChkZeroes(operand *op, int lit,  int size)
3777 {
3778         
3779         int i;
3780         int flag =1;
3781         
3782         while(size--) {
3783                 i = (lit >> (size*8)) & 0xff;
3784                 
3785                 if(i==0) {
3786                         if(flag) 
3787                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3788                         else
3789                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3790                         flag = 0;
3791                 }
3792         }
3793         
3794         return (flag==0);
3795 }
3796 #endif
3797
3798 /*-----------------------------------------------------------------*/
3799 /* genCmp :- greater or less than comparison                       */
3800 /*-----------------------------------------------------------------*/
3801 static void genCmp (operand *left,operand *right,
3802                                         operand *result, iCode *ifx, int sign)
3803 {
3804         int size; //, offset = 0 ;
3805         unsigned long lit = 0L,i = 0;
3806         resolvedIfx rFalseIfx;
3807         //  resolvedIfx rTrueIfx;
3808         symbol *truelbl;
3809
3810         FENTRY;
3811         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3812         /*
3813         if(ifx) {
3814         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3815         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3816         }
3817         */
3818         
3819         resolveIfx(&rFalseIfx,ifx);
3820         truelbl  = newiTempLabel(NULL);
3821         size = max(AOP_SIZE(left),AOP_SIZE(right));
3822         
3823         DEBUGpic14_AopType(__LINE__,left,right,result);
3824         
3825 #define _swapp
3826         
3827         /* if literal is on the right then swap with left */
3828         if ((AOP_TYPE(right) == AOP_LIT)) {
3829                 operand *tmp = right ;
3830                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
3831                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3832 #ifdef _swapp
3833                 
3834                 lit = (lit - 1) & mask;
3835                 right = left;
3836                 left = tmp;
3837                 rFalseIfx.condition ^= 1;
3838 #endif
3839                 
3840         } else if ((AOP_TYPE(left) == AOP_LIT)) {
3841                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3842         }
3843         
3844         
3845         //if(IC_TRUE(ifx) == NULL)
3846         /* if left & right are bit variables */
3847         if (AOP_TYPE(left) == AOP_CRY &&
3848                 AOP_TYPE(right) == AOP_CRY ) {
3849                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3850                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3851         } else {
3852         /* subtract right from left if at the
3853         end the carry flag is set then we know that
3854                 left is greater than right */
3855                 
3856                 symbol *lbl  = newiTempLabel(NULL);
3857                 
3858 #ifndef _swapp
3859                 if(AOP_TYPE(right) == AOP_LIT) {
3860                         
3861                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3862                         
3863                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3864                         
3865                         /* special cases */
3866                         
3867                         if(lit == 0) {
3868                                 
3869                                 if(sign != 0) 
3870                                         genSkipCond(&rFalseIfx,left,size-1,7);
3871                                 else 
3872                                         /* no need to compare to 0...*/
3873                                         /* NOTE: this is a de-generate compare that most certainly 
3874                                         *       creates some dead code. */
3875                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3876                                 
3877                                 if(ifx) ifx->generated = 1;
3878                                 return;
3879                                 
3880                         }
3881                         size--;
3882                         
3883                         if(size == 0) {
3884                                 //i = (lit >> (size*8)) & 0xff;
3885                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3886                                 
3887                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3888                                 
3889                                 i = ((0-lit) & 0xff);
3890                                 if(sign) {
3891                                         if( i == 0x81) { 
3892                                         /* lit is 0x7f, all signed chars are less than
3893                                                 * this except for 0x7f itself */
3894                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
3895                                                 genSkipz2(&rFalseIfx,0);
3896                                         } else {
3897                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
3898                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
3899                                                 genSkipc(&rFalseIfx);
3900                                         }
3901                                         
3902                                 } else {
3903                                         if(lit == 1) {
3904                                                 genSkipz2(&rFalseIfx,1);
3905                                         } else {
3906                                                 emitpcode(POC_ADDLW, popGetLit(i));
3907                                                 genSkipc(&rFalseIfx);
3908                                         }
3909                                 }
3910                                 
3911                                 if(ifx) ifx->generated = 1;
3912                                 return;
3913                         }
3914                         
3915                         /* chars are out of the way. now do ints and longs */
3916                         
3917                         
3918                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3919                         
3920                         /* special cases */
3921                         
3922                         if(sign) {
3923                                 
3924                                 if(lit == 0) {
3925                                         genSkipCond(&rFalseIfx,left,size,7);
3926                                         if(ifx) ifx->generated = 1;
3927                                         return;
3928                                 }
3929                                 
3930                                 if(lit <0x100) {
3931                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3932                                         
3933                                         //rFalseIfx.condition ^= 1;
3934                                         //genSkipCond(&rFalseIfx,left,size,7);
3935                                         //rFalseIfx.condition ^= 1;
3936                                         
3937                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3938                                         if(rFalseIfx.condition)
3939                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3940                                         else
3941                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3942                                         
3943                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3944                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
3945                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
3946                                         
3947                                         while(size > 1)
3948                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
3949                                         
3950                                         if(rFalseIfx.condition) {
3951                                                 emitSKPZ;
3952                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3953                                                 
3954                                         } else {
3955                                                 emitSKPNZ;
3956                                         }
3957                                         
3958                                         genSkipc(&rFalseIfx);
3959                                         emitpLabel(truelbl->key);
3960                                         if(ifx) ifx->generated = 1;
3961                                         return;
3962                                         
3963                                 }
3964                                 
3965                                 if(size == 1) {
3966                                         
3967                                         if( (lit & 0xff) == 0) {
3968                                                 /* lower byte is zero */
3969                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3970                                                 i = ((lit >> 8) & 0xff) ^0x80;
3971                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3972                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
3973                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3974                                                 genSkipc(&rFalseIfx);
3975                                                 
3976                                                 
3977                                                 if(ifx) ifx->generated = 1;
3978                                                 return;
3979                                                 
3980                                         }
3981                                 } else {
3982                                         /* Special cases for signed longs */
3983                                         if( (lit & 0xffffff) == 0) {
3984                                                 /* lower byte is zero */
3985                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3986                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
3987                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3988                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
3989                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3990                                                 genSkipc(&rFalseIfx);
3991                                                 
3992                                                 
3993                                                 if(ifx) ifx->generated = 1;
3994                                                 return;
3995                                                 
3996                                         }
3997                                         
3998                                 }
3999                                 
4000                                 
4001                                 if(lit & (0x80 << (size*8))) {
4002                                         /* lit is negative */
4003                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4004                                         
4005                                         //genSkipCond(&rFalseIfx,left,size,7);
4006                                         
4007                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4008                                         
4009                                         if(rFalseIfx.condition)
4010                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4011                                         else
4012                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4013                                         
4014                                         
4015                                 } else {
4016                                         /* lit is positive */
4017                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4018                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4019                                         if(rFalseIfx.condition)
4020                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4021                                         else
4022                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4023                                         
4024                                 }
4025                                 
4026                                 /* There are no more special cases, so perform a general compare */
4027                                 
4028                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4029                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4030                                 
4031                                 while(size--) {
4032                                         
4033                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4034                                         emitSKPNZ;
4035                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4036                                 }
4037                                 //rFalseIfx.condition ^= 1;
4038                                 genSkipc(&rFalseIfx);
4039                                 
4040                                 emitpLabel(truelbl->key);
4041                                 
4042                                 if(ifx) ifx->generated = 1;
4043                                 return;
4044                                 
4045                                 
4046                         }
4047
4048
4049                         /* sign is out of the way. So now do an unsigned compare */
4050                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4051
4052
4053                         /* General case - compare to an unsigned literal on the right.*/
4054
4055                         i = (lit >> (size*8)) & 0xff;
4056                         emitpcode(POC_MOVLW, popGetLit(i));
4057                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4058                         while(size--) {
4059                                 i = (lit >> (size*8)) & 0xff;
4060                                 
4061                                 if(i) {
4062                                         emitpcode(POC_MOVLW, popGetLit(i));
4063                                         emitSKPNZ;
4064                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4065                                 } else {
4066                                 /* this byte of the lit is zero, 
4067                                         *if it's not the last then OR in the variable */
4068                                         if(size)
4069                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4070                                 }
4071                         }
4072
4073
4074                 emitpLabel(lbl->key);
4075                 //if(emitFinalCheck)
4076                 genSkipc(&rFalseIfx);
4077                 if(sign)
4078                         emitpLabel(truelbl->key);
4079
4080                 if(ifx) ifx->generated = 1;
4081                 return;
4082
4083
4084                 }
4085 #endif  // _swapp
4086
4087                 if(AOP_TYPE(left) == AOP_LIT) {
4088                         //symbol *lbl = newiTempLabel(NULL);
4089                         
4090                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4091                         
4092                         
4093                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4094                         
4095                         /* Special cases */
4096                         if((lit == 0) && (sign == 0)){
4097                                 
4098                                 size--;
4099                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4100                                 while(size) 
4101                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4102                                 
4103                                 genSkipz2(&rFalseIfx,0);
4104                                 if(ifx) ifx->generated = 1;
4105                                 return;
4106                         }
4107                         
4108                         if(size==1) {
4109                                 /* Special cases */
4110                                 lit &= 0xff;
4111                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4112                                         /* degenerate compare can never be true */
4113                                         if(rFalseIfx.condition == 0)
4114                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4115                                         
4116                                         if(ifx) ifx->generated = 1;
4117                                         return;
4118                                 }
4119                                 
4120                                 if(sign) {
4121                                         /* signed comparisons to a literal byte */
4122                                         
4123                                         int lp1 = (lit+1) & 0xff;
4124                                         
4125                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4126                                         switch (lp1) {
4127                                         case 0:
4128                                                 rFalseIfx.condition ^= 1;
4129                                                 genSkipCond(&rFalseIfx,right,0,7);
4130                                                 break;
4131                                         case 0x7f:
4132                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4133                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4134                                                 genSkipz2(&rFalseIfx,1);
4135                                                 break;
4136                                         default:
4137                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4138                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4139                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4140                                                 rFalseIfx.condition ^= 1;
4141                                                 genSkipc(&rFalseIfx);
4142                                                 break;
4143                                         }
4144                                         if(ifx) ifx->generated = 1;
4145                                 } else {
4146                                         /* unsigned comparisons to a literal byte */
4147                                         
4148                                         switch(lit & 0xff ) {
4149                                         case 0:
4150                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4151                                                 genSkipz2(&rFalseIfx,0);
4152                                                 if(ifx) ifx->generated = 1;
4153                                                 break;
4154                                         case 0x7f:
4155                                                 genSkipCond(&rFalseIfx,right,0,7);
4156                                                 if(ifx) ifx->generated = 1;
4157                                                 break;
4158                                                 
4159                                         default:
4160                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4161                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4162                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4163                                                 rFalseIfx.condition ^= 1;
4164                                                 if (AOP_TYPE(result) == AOP_CRY) {
4165                                                         genSkipc(&rFalseIfx);
4166                                                         if(ifx) ifx->generated = 1;
4167                                                 } else {
4168                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4169                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4170                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4171                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4172                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4173                                                 }       
4174                                                 break;
4175                                         }
4176                                 }
4177                                 
4178                                 //goto check_carry;
4179                                 return;
4180                                 
4181                         } else {
4182                                 
4183                                 /* Size is greater than 1 */
4184                                 
4185                                 if(sign) {
4186                                         int lp1 = lit+1;
4187                                         
4188                                         size--;
4189                                         
4190                                         if(lp1 == 0) {
4191                                                 /* this means lit = 0xffffffff, or -1 */
4192                                                 
4193                                                 
4194                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4195                                                 rFalseIfx.condition ^= 1;
4196                                                 genSkipCond(&rFalseIfx,right,size,7);
4197                                                 if(ifx) ifx->generated = 1;
4198                                                 return;
4199                                         }
4200                                         
4201                                         if(lit == 0) {
4202                                                 int s = size;
4203                                                 
4204                                                 if(rFalseIfx.condition) {
4205                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4206                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4207                                                 }
4208                                                 
4209                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4210                                                 while(size--)
4211                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4212                                                 
4213                                                 
4214                                                 emitSKPZ;
4215                                                 if(rFalseIfx.condition) {
4216                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4217                                                         emitpLabel(truelbl->key);
4218                                                 }else {
4219                                                         rFalseIfx.condition ^= 1;
4220                                                         genSkipCond(&rFalseIfx,right,s,7);
4221                                                 }
4222                                                 
4223                                                 if(ifx) ifx->generated = 1;
4224                                                 return;
4225                                         }
4226                                         
4227                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4228                                                 /* lower byte of signed word is zero */
4229                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4230                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4231                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4232                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4233                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4234                                                 rFalseIfx.condition ^= 1;
4235                                                 genSkipc(&rFalseIfx);
4236                                                 
4237                                                 
4238                                                 if(ifx) ifx->generated = 1;
4239                                                 return;
4240                                         }
4241                                         
4242                                         if(lit & (0x80 << (size*8))) {
4243                                                 /* Lit is less than zero */
4244                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4245                                                 //rFalseIfx.condition ^= 1;
4246                                                 //genSkipCond(&rFalseIfx,left,size,7);
4247                                                 //rFalseIfx.condition ^= 1;
4248                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4249                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4250                                                 
4251                                                 if(rFalseIfx.condition)
4252                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4253                                                 else
4254                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4255                                                 
4256                                                 
4257                                         } else {
4258                                                 /* Lit is greater than or equal to zero */
4259                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4260                                                 //rFalseIfx.condition ^= 1;
4261                                                 //genSkipCond(&rFalseIfx,right,size,7);
4262                                                 //rFalseIfx.condition ^= 1;
4263                                                 
4264                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4265                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4266                                                 
4267                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4268                                                 if(rFalseIfx.condition)
4269                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4270                                                 else
4271                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4272                                                 
4273                                         }
4274                                         
4275                                         
4276                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4277                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4278                                         
4279                                         while(size--) {
4280                                                 
4281                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4282                                                 emitSKPNZ;
4283                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4284                                         }
4285                                         rFalseIfx.condition ^= 1;
4286                                         //rFalseIfx.condition = 1;
4287                                         genSkipc(&rFalseIfx);
4288                                         
4289                                         emitpLabel(truelbl->key);
4290                                         
4291                                         if(ifx) ifx->generated = 1;
4292                                         return;
4293                                         // end of if (sign)
4294                                 } else {
4295                                         
4296                                         /* compare word or long to an unsigned literal on the right.*/
4297                                         
4298                                         
4299                                         size--;
4300                                         if(lit < 0xff) {
4301                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4302                                                 switch (lit) {
4303                                                 case 0:
4304                                                         break; /* handled above */
4305                                                 /*
4306                                                 case 0xff:
4307                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4308                                                         while(size--)
4309                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4310                                                         genSkipz2(&rFalseIfx,0);
4311                                                         break;
4312                                                 */
4313                                                 default:
4314                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4315                                                         while(--size)
4316                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4317                                                         
4318                                                         emitSKPZ;
4319                                                         if(rFalseIfx.condition)
4320                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4321                                                         else
4322                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4323                                                         
4324                                                         
4325                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4326                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4327                                                         
4328                                                         rFalseIfx.condition ^= 1;
4329                                                         genSkipc(&rFalseIfx);
4330                                                 }
4331                                                 
4332                                                 emitpLabel(truelbl->key);
4333                                                 
4334                                                 if(ifx) ifx->generated = 1;
4335                                                 return;
4336                                         }
4337                                         
4338                                         
4339                                         lit++;
4340                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4341                                         i = (lit >> (size*8)) & 0xff;
4342                                         
4343                                         emitpcode(POC_MOVLW, popGetLit(i));
4344                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4345                                         
4346                                         while(size--) {
4347                                                 i = (lit >> (size*8)) & 0xff;
4348                                                 
4349                                                 if(i) {
4350                                                         emitpcode(POC_MOVLW, popGetLit(i));
4351                                                         emitSKPNZ;
4352                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4353                                                 } else {
4354                                                 /* this byte of the lit is zero, 
4355                                                         *if it's not the last then OR in the variable */
4356                                                         if(size)
4357                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4358                                                 }
4359                                         }
4360                                         
4361                                         
4362                                         emitpLabel(lbl->key);
4363                                         
4364                                         rFalseIfx.condition ^= 1;
4365                                         genSkipc(&rFalseIfx);
4366                                 }
4367                                 
4368                                 if(sign)
4369                                         emitpLabel(truelbl->key);
4370                                 if(ifx) ifx->generated = 1;
4371                                 return;
4372                         }
4373                 }
4374                 /* Compare two variables */
4375                 
4376                 DEBUGpic14_emitcode(";sign","%d",sign);
4377                 
4378                 size--;
4379                 if(sign) {
4380                         /* Sigh. thus sucks... */
4381                         if(size) {
4382                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4383                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4384                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4385                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4386                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4387                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4388                         } else {
4389                                 /* Signed char comparison */
4390                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4391                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4392                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4393                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4394                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4395                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4396                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4397                                 
4398                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4399                                 genSkipc(&rFalseIfx);
4400                                 
4401                                 if(ifx) ifx->generated = 1;
4402                                 return;
4403                         }
4404                         
4405                 } else {
4406                         
4407                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4408                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4409                 }
4410                 
4411                 
4412                 /* The rest of the bytes of a multi-byte compare */
4413                 while (size) {
4414                         
4415                         emitSKPZ;
4416                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4417                         size--;
4418                         
4419                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4420                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4421                         
4422                         
4423                 }
4424                 
4425                 emitpLabel(lbl->key);
4426                 
4427                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4428                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4429                         (AOP_TYPE(result) == AOP_REG)) {
4430                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4431                         emitpcode(POC_RLF, popGet(AOP(result),0));
4432                 } else {
4433                         genSkipc(&rFalseIfx);
4434                 }       
4435                 //genSkipc(&rFalseIfx);
4436                 if(ifx) ifx->generated = 1;
4437                 
4438                 return;
4439                 
4440         }
4441         
4442         // check_carry:
4443         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4444                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4445                 pic14_outBitC(result);
4446         } else {
4447                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4448                 /* if the result is used in the next
4449                 ifx conditional branch then generate
4450                 code a little differently */
4451                 if (ifx )
4452                         genIfxJump (ifx,"c");
4453                 else
4454                         pic14_outBitC(result);
4455                 /* leave the result in acc */
4456         }
4457         
4458 }
4459
4460 /*-----------------------------------------------------------------*/
4461 /* genCmpGt :- greater than comparison                             */
4462 /*-----------------------------------------------------------------*/
4463 static void genCmpGt (iCode *ic, iCode *ifx)
4464 {
4465         operand *left, *right, *result;
4466         sym_link *letype , *retype;
4467         int sign ;
4468         
4469         FENTRY;
4470         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4471         left = IC_LEFT(ic);
4472         right= IC_RIGHT(ic);
4473         result = IC_RESULT(ic);
4474         
4475         letype = getSpec(operandType(left));
4476         retype =getSpec(operandType(right));
4477         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4478         /* assign the amsops */
4479         aopOp (left,ic,FALSE);
4480         aopOp (right,ic,FALSE);
4481         aopOp (result,ic,TRUE);
4482         
4483         genCmp(right, left, result, ifx, sign);
4484         
4485         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4486         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4487         freeAsmop(result,NULL,ic,TRUE); 
4488 }
4489
4490 /*-----------------------------------------------------------------*/
4491 /* genCmpLt - less than comparisons                                */
4492 /*-----------------------------------------------------------------*/
4493 static void genCmpLt (iCode *ic, iCode *ifx)
4494 {
4495         operand *left, *right, *result;
4496         sym_link *letype , *retype;
4497         int sign ;
4498         
4499         FENTRY;
4500         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4501         left = IC_LEFT(ic);
4502         right= IC_RIGHT(ic);
4503         result = IC_RESULT(ic);
4504         
4505         letype = getSpec(operandType(left));
4506         retype =getSpec(operandType(right));
4507         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4508         
4509         /* assign the amsops */
4510         aopOp (left,ic,FALSE);
4511         aopOp (right,ic,FALSE);
4512         aopOp (result,ic,TRUE);
4513         
4514         genCmp(left, right, result, ifx, sign);
4515         
4516         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4517         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4518         freeAsmop(result,NULL,ic,TRUE); 
4519 }
4520
4521 /*-----------------------------------------------------------------*/
4522 /* genc16bit2lit - compare a 16 bit value to a literal             */
4523 /*-----------------------------------------------------------------*/
4524 static void genc16bit2lit(operand *op, int lit, int offset)
4525 {
4526         int i;
4527         
4528         FENTRY;
4529         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4530         if( (lit&0xff) == 0) 
4531                 i=1;
4532         else
4533                 i=0;
4534         
4535         switch( BYTEofLONG(lit,i)) { 
4536         case 0:
4537                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4538                 break;
4539         case 1:
4540                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4541                 break;
4542         case 0xff:
4543                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4544                 break;
4545         default:
4546                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4547                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4548         }
4549         
4550         i ^= 1;
4551         
4552         switch( BYTEofLONG(lit,i)) { 
4553         case 0:
4554                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4555                 break;
4556         case 1:
4557                 emitSKPNZ;
4558                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4559                 break;
4560         case 0xff:
4561                 emitSKPNZ;
4562                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4563                 break;
4564         default:
4565                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4566                 emitSKPNZ;
4567                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4568                 
4569         }
4570         
4571 }
4572
4573 /*-----------------------------------------------------------------*/
4574 /* gencjneshort - compare and jump if not equal                    */
4575 /*-----------------------------------------------------------------*/
4576 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4577 {
4578         int size = max(AOP_SIZE(left),AOP_SIZE(right));
4579         int offset = 0;
4580         int res_offset = 0;  /* the result may be a different size then left or right */
4581         int res_size = AOP_SIZE(result);
4582         resolvedIfx rIfx;
4583         symbol *lbl;
4584         
4585         unsigned long lit = 0L;
4586         FENTRY;
4587         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4588           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4589           return;
4590         }
4591         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4592         DEBUGpic14_AopType(__LINE__,left,right,result);
4593         if(result)
4594                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4595         resolveIfx(&rIfx,ifx);
4596         lbl =  newiTempLabel(NULL);
4597         
4598         
4599         /* if the left side is a literal or 
4600         if the right is in a pointer register and left 
4601         is not */
4602         if ((AOP_TYPE(left) == AOP_LIT) || 
4603                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4604                 operand *t = right;
4605                 right = left;
4606                 left = t;
4607         }
4608         if(AOP_TYPE(right) == AOP_LIT)
4609                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4610         
4611         /* if the right side is a literal then anything goes */
4612         if (AOP_TYPE(right) == AOP_LIT &&
4613                 AOP_TYPE(left) != AOP_DIR ) {
4614                 switch(size) {
4615                 case 2:
4616                         genc16bit2lit(left, lit, 0);
4617                         emitSKPNZ;
4618                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4619                         break;
4620                 default:
4621                         while (size--) {
4622                                 if(lit & 0xff) {
4623                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4624                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4625                                 } else {
4626                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4627                                 }
4628                                 
4629                                 emitSKPNZ;
4630                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4631                                 offset++;
4632                                 if(res_offset < res_size-1)
4633                                         res_offset++;
4634                                 lit >>= 8;
4635                         }
4636                         break;
4637                 }
4638         }
4639         
4640         /* if the right side is in a register or in direct space or
4641         if the left is a pointer register & right is not */    
4642         else if (AOP_TYPE(right) == AOP_REG ||
4643                 AOP_TYPE(right) == AOP_DIR || 
4644                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4645                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4646                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4647                 int lbl_key = lbl->key;
4648                 
4649                 if(result) {
4650                         if (AOP_TYPE(result) != AOP_CRY)
4651                                 emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4652                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4653                 }else {
4654                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4655                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4656                                 __FUNCTION__,__LINE__);
4657                         return;
4658                 }
4659                 
4660                 /*     switch(size) { */
4661                 /*     case 2: */
4662                 /*       genc16bit2lit(left, lit, 0); */
4663                 /*       emitSKPNZ; */
4664                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4665                 /*       break; */
4666                 /*     default: */
4667                 while (size--) {
4668                         int emit_skip=1;
4669                         if((AOP_TYPE(left) == AOP_DIR) && 
4670                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4671                                 
4672                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4673                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4674                                 
4675                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4676                                 
4677                                 switch (lit & 0xff) {
4678                                 case 0:
4679                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4680                                         break;
4681                                 case 1:
4682                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4683                                         emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4684                                         //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4685                                         emit_skip=0;
4686                                         break;
4687                                 case 0xff:
4688                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4689                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4690                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4691                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4692                                         emit_skip=0;
4693                                         break;
4694                                 default:
4695                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4696                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4697                                 }
4698                                 lit >>= 8;
4699                                 
4700                         } else {
4701                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4702                         }
4703                         if(emit_skip) {
4704                                 if(AOP_TYPE(result) == AOP_CRY) {
4705                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4706                                         if(rIfx.condition)
4707                                                 emitSKPNZ;
4708                                         else
4709                                                 emitSKPZ;
4710                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4711                                 } else {
4712                                         /* fix me. probably need to check result size too */
4713                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
4714                                         if(rIfx.condition)
4715                                                 emitSKPZ;
4716                                         else
4717                                                 emitSKPNZ;
4718                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4719                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4720                                 }
4721                                 if(ifx)
4722                                         ifx->generated=1;
4723                         }
4724                         emit_skip++;
4725                         offset++;
4726                         if(res_offset < res_size-1)
4727                                 res_offset++;
4728                 }
4729                 /*       break; */
4730                 /*     } */
4731         } else if(AOP_TYPE(right) == AOP_REG &&
4732                 AOP_TYPE(left) != AOP_DIR){
4733                 
4734                 while(size--) {
4735                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4736                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4737                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4738                         if(rIfx.condition)
4739                                 emitSKPNZ;
4740                         else
4741                                 emitSKPZ;
4742                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4743                         offset++;
4744                         if(res_offset < res_size-1)
4745                                 res_offset++;
4746                 }
4747                 
4748         }else{
4749                 /* right is a pointer reg need both a & b */
4750                 while(size--) {
4751                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4752                         if(strcmp(l,"b"))
4753                                 pic14_emitcode("mov","b,%s",l);
4754                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4755                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4756                         offset++;
4757                 }
4758         }
4759         
4760         emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4761         if(!rIfx.condition)
4762                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4763         
4764         emitpLabel(lbl->key);
4765         
4766         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4767         
4768         if(ifx)
4769                 ifx->generated = 1;
4770 }
4771
4772 #if 0
4773 /*-----------------------------------------------------------------*/
4774 /* gencjne - compare and jump if not equal                         */
4775 /*-----------------------------------------------------------------*/
4776 static void gencjne(operand *left, operand *right, iCode *ifx)
4777 {
4778         symbol *tlbl  = newiTempLabel(NULL);
4779         
4780         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4781         gencjneshort(left, right, lbl);
4782         
4783         pic14_emitcode("mov","a,%s",one);
4784         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4785         pic14_emitcode("","%05d_DS_:",lbl->key+100);
4786         pic14_emitcode("clr","a");
4787         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4788         
4789         emitpLabel(lbl->key);
4790         emitpLabel(tlbl->key);
4791         
4792 }
4793 #endif
4794
4795 /*-----------------------------------------------------------------*/
4796 /* genCmpEq - generates code for equal to                          */
4797 /*-----------------------------------------------------------------*/
4798 static void genCmpEq (iCode *ic, iCode *ifx)
4799 {
4800         operand *left, *right, *result;
4801         unsigned long lit = 0L;
4802         int size,offset=0;
4803         
4804         FENTRY;
4805         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4806         
4807         if(ifx)
4808                 DEBUGpic14_emitcode ("; ifx is non-null","");
4809         else
4810                 DEBUGpic14_emitcode ("; ifx is null","");
4811         
4812         aopOp((left=IC_LEFT(ic)),ic,FALSE);
4813         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4814         aopOp((result=IC_RESULT(ic)),ic,TRUE);
4815         
4816         size = max(AOP_SIZE(left),AOP_SIZE(right));
4817         
4818         DEBUGpic14_AopType(__LINE__,left,right,result);
4819         
4820         /* if literal, literal on the right or 
4821         if the right is in a pointer register and left 
4822         is not */
4823         if (aop_isLitLike (AOP(IC_LEFT(ic)))
4824                         || (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4825                 operand *tmp = right ;
4826                 right = left;
4827                 left = tmp;
4828         }
4829         
4830         
4831         if(ifx && !AOP_SIZE(result)){
4832                 symbol *tlbl;
4833                 /* if they are both bit variables */
4834                 if (AOP_TYPE(left) == AOP_CRY &&
4835                         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4836                         if(AOP_TYPE(right) == AOP_LIT){
4837                                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4838                                 if(lit == 0L){
4839                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4840                                         pic14_emitcode("cpl","c");
4841                                 } else if(lit == 1L) {
4842                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4843                                 } else {
4844                                         pic14_emitcode("clr","c");
4845                                 }
4846                                 /* AOP_TYPE(right) == AOP_CRY */
4847                         } else {
4848                                 symbol *lbl = newiTempLabel(NULL);
4849                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4850                                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4851                                 pic14_emitcode("cpl","c");
4852                                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4853                         }
4854                         /* if true label then we jump if condition
4855                         supplied is true */
4856                         tlbl = newiTempLabel(NULL);
4857                         if ( IC_TRUE(ifx) ) {
4858                                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4859                                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4860                         } else {
4861                                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4862                                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4863                         }
4864                         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4865                         
4866                         {
4867                                 /* left and right are both bit variables, result is carry */
4868                                 resolvedIfx rIfx;
4869                                 
4870                                 resolveIfx(&rIfx,ifx);
4871                                 
4872                                 emitpcode(POC_MOVLW,popGet(AOP(left),0));
4873                                 emitpcode(POC_ANDFW,popGet(AOP(left),0));
4874                                 emitpcode(POC_BTFSC,popGet(AOP(right),0));
4875                                 emitpcode(POC_ANDLW,popGet(AOP(left),0));
4876                                 genSkipz2(&rIfx,0);
4877                         }
4878                 } else {
4879                         
4880                         /* They're not both bit variables. Is the right a literal? */
4881                         if(AOP_TYPE(right) == AOP_LIT) {
4882                                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4883                                 
4884                                 switch(size) {
4885                                         
4886                                 case 1:
4887                                         switch(lit & 0xff) {
4888                                         case 1:
4889                                                 if ( IC_TRUE(ifx) ) {
4890                                                         emitpcode(POC_DECFW,popGet(AOP(left),offset));
4891                                                         emitSKPNZ;
4892                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4893                                                 } else {
4894                                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4895                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4896                                                 }
4897                                                 break;
4898                                         case 0xff:
4899                                                 if ( IC_TRUE(ifx) ) {
4900                                                         emitpcode(POC_INCFW,popGet(AOP(left),offset));
4901                                                         emitSKPNZ;
4902                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4903                                                 } else {
4904                                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4905                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4906                                                 }
4907                                                 break;
4908                                         default:
4909                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4910                                                 if(lit)
4911                                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4912                                                 genSkip(ifx,'z');
4913                                         }
4914                                         
4915                                         
4916                                         /* end of size == 1 */
4917                                         break;
4918                                         
4919                                         case 2:
4920                                                 genc16bit2lit(left,lit,offset);
4921                                                 genSkip(ifx,'z');
4922                                                 break;
4923                                                 /* end of size == 2 */
4924                                                 
4925                                         default:
4926                                                 /* size is 4 */
4927                                                 if(lit==0) {
4928                                                         emitpcode(POC_MOVFW,popGet(AOP(left),0));
4929                                                         emitpcode(POC_IORFW,popGet(AOP(left),1));
4930                                                         emitpcode(POC_IORFW,popGet(AOP(left),2));
4931                                                         emitpcode(POC_IORFW,popGet(AOP(left),3));
4932                                                         
4933                                                 } else {
4934                                                         
4935                                                         /* search for patterns that can be optimized */
4936                                                         
4937                                                         genc16bit2lit(left,lit,0);
4938                                                         lit >>= 16;
4939                                                         if(lit) {
4940                                                                 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4941                                                                 //genSkip(ifx,'z');
4942                                                                 genc16bit2lit(left,lit,2);
4943                                                         } else {
4944                                                                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4945                                                                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4946                                                                 
4947                                                         }
4948                                                         
4949                                                 }
4950                                                 
4951                                                 genSkip(ifx,'z');
4952                                 }
4953                                 
4954                                 ifx->generated = 1;
4955                                 goto release ;
4956                                 
4957                                 
4958                         } else if(AOP_TYPE(right) == AOP_CRY ) {
4959                                 /* we know the left is not a bit, but that the right is */
4960                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4961                                 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4962                                         popGet(AOP(right),offset));
4963                                 emitpcode(POC_XORLW,popGetLit(1));
4964                                 
4965                                 /* if the two are equal, then W will be 0 and the Z bit is set
4966                                 * we could test Z now, or go ahead and check the high order bytes if
4967                                 * the variable we're comparing is larger than a byte. */
4968                                 
4969                                 while(--size)
4970                                         emitpcode(POC_IORFW,popGet(AOP(left),offset));
4971                                 
4972                                 if ( IC_TRUE(ifx) ) {
4973                                         emitSKPNZ;
4974                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4975                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4976                                 } else {
4977                                         emitSKPZ;
4978                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4979                                         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4980                                 }
4981                                 
4982                         } else {
4983                                 /* They're both variables that are larger than bits */
4984                                 int s = size;
4985                                 
4986                                 tlbl = newiTempLabel(NULL);
4987                                 
4988                                 while(size--) {
4989                                         mov2w (AOP(right),offset); /* right might be litLike() */
4990                                         emitpcode(POC_XORFW,popGet(AOP(left),offset));
4991                                         
4992                                         if ( IC_TRUE(ifx) ) {
4993                                                 if(size) {
4994                                                         emitSKPZ;
4995                                                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
4996                                                         pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
4997                                                 } else {
4998                                                         emitSKPNZ;
4999                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5000                                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5001                                                 }
5002                                         } else {
5003                                                 emitSKPZ;
5004                                                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5005                                                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5006                                         }
5007                                         offset++;
5008                                 }
5009                                 if(s>1 && IC_TRUE(ifx)) {
5010                                         emitpLabel(tlbl->key);
5011                                         pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5012                                 }
5013                         }
5014                 }
5015                 /* mark the icode as generated */
5016                 ifx->generated = 1;
5017                 goto release ;
5018         }
5019   
5020   /* if they are both bit variables */
5021   if (AOP_TYPE(left) == AOP_CRY &&
5022           ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5023           if(AOP_TYPE(right) == AOP_LIT){
5024                   unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5025                   if(lit == 0L){
5026                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5027                           pic14_emitcode("cpl","c");
5028                   } else if(lit == 1L) {
5029                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5030                   } else {
5031                           pic14_emitcode("clr","c");
5032                   }
5033                   /* AOP_TYPE(right) == AOP_CRY */
5034           } else {
5035                   symbol *lbl = newiTempLabel(NULL);
5036                   pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5037                   pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5038                   pic14_emitcode("cpl","c");
5039                   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5040           }
5041           /* c = 1 if egal */
5042           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5043                   pic14_outBitC(result);
5044                   goto release ;
5045           }
5046           if (ifx) {
5047                   genIfxJump (ifx,"c");
5048                   goto release ;
5049           }
5050           /* if the result is used in an arithmetic operation
5051           then put the result in place */
5052           pic14_outBitC(result);
5053   } else {
5054           
5055           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5056           gencjne(left,right,result,ifx);
5057           /*
5058           if(ifx) 
5059           gencjne(left,right,newiTempLabel(NULL));
5060           else {
5061           if(IC_TRUE(ifx)->key)
5062           gencjne(left,right,IC_TRUE(ifx)->key);
5063           else
5064           gencjne(left,right,IC_FALSE(ifx)->key);
5065           ifx->generated = 1;
5066           goto release ;
5067           }
5068           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5069           aopPut(AOP(result),"a",0);
5070           goto release ;
5071           }
5072           
5073                 if (ifx) {
5074                 genIfxJump (ifx,"a");
5075                 goto release ;
5076                 }
5077           */
5078           /* if the result is used in an arithmetic operation
5079           then put the result in place */
5080           /*
5081           if (AOP_TYPE(result) != AOP_CRY) 
5082           pic14_outAcc(result);
5083           */
5084           /* leave the result in acc */
5085   }
5086   
5087 release:
5088   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5089   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5090   freeAsmop(result,NULL,ic,TRUE);
5091 }
5092
5093 /*-----------------------------------------------------------------*/
5094 /* ifxForOp - returns the icode containing the ifx for operand     */
5095 /*-----------------------------------------------------------------*/
5096 static iCode *ifxForOp ( operand *op, iCode *ic )
5097 {
5098         FENTRY;
5099         /* if true symbol then needs to be assigned */
5100         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5101         if (IS_TRUE_SYMOP(op))
5102                 return NULL ;
5103         
5104         /* if this has register type condition and
5105         the next instruction is ifx with the same operand
5106         and live to of the operand is upto the ifx only then */
5107         if (ic->next &&
5108                 ic->next->op == IFX &&
5109                 IC_COND(ic->next)->key == op->key &&
5110                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5111                 return ic->next;
5112         
5113         if (ic->next &&
5114                 ic->next->op == IFX &&
5115                 IC_COND(ic->next)->key == op->key) {
5116                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5117                 return ic->next;
5118         }
5119         
5120         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5121         if (ic->next &&
5122                 ic->next->op == IFX)
5123                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5124         
5125         if (ic->next &&
5126                 ic->next->op == IFX &&
5127                 IC_COND(ic->next)->key == op->key) {
5128                 DEBUGpic14_emitcode ("; "," key is okay");
5129                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5130                         OP_SYMBOL(op)->liveTo,
5131                         ic->next->seq);
5132         }
5133         
5134         
5135         return NULL;
5136 }
5137 /*-----------------------------------------------------------------*/
5138 /* genAndOp - for && operation                                     */
5139 /*-----------------------------------------------------------------*/
5140 static void genAndOp (iCode *ic)
5141 {
5142         operand *left,*right, *result;
5143         /*     symbol *tlbl; */
5144         
5145         FENTRY;
5146         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5147         /* note here that && operations that are in an
5148         if statement are taken away by backPatchLabels
5149         only those used in arthmetic operations remain */
5150         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5151         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5152         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5153         
5154         DEBUGpic14_AopType(__LINE__,left,right,result);
5155         
5156         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5157         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5158         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5159         
5160         /* if both are bit variables */
5161         /*     if (AOP_TYPE(left) == AOP_CRY && */
5162         /*         AOP_TYPE(right) == AOP_CRY ) { */
5163         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5164         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5165         /*         pic14_outBitC(result); */
5166         /*     } else { */
5167         /*         tlbl = newiTempLabel(NULL); */
5168         /*         pic14_toBoolean(left);     */
5169         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5170         /*         pic14_toBoolean(right); */
5171         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5172         /*         pic14_outBitAcc(result); */
5173         /*     } */
5174         
5175         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5176         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5177         freeAsmop(result,NULL,ic,TRUE);
5178 }
5179
5180
5181 /*-----------------------------------------------------------------*/
5182 /* genOrOp - for || operation                                      */
5183 /*-----------------------------------------------------------------*/
5184 /*
5185 tsd pic port -
5186 modified this code, but it doesn't appear to ever get called
5187 */
5188
5189 static void genOrOp (iCode *ic)
5190 {
5191         operand *left,*right, *result;
5192         symbol *tlbl;
5193         
5194         /* note here that || operations that are in an
5195         if statement are taken away by backPatchLabels
5196         only those used in arthmetic operations remain */
5197         FENTRY;
5198         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5199         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5200         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5201         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5202         
5203         DEBUGpic14_AopType(__LINE__,left,right,result);
5204         
5205         /* if both are bit variables */
5206         if (AOP_TYPE(left) == AOP_CRY &&
5207                 AOP_TYPE(right) == AOP_CRY ) {
5208                 pic14_emitcode("clrc","");
5209                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5210                         AOP(left)->aopu.aop_dir,
5211                         AOP(left)->aopu.aop_dir);
5212                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5213                         AOP(right)->aopu.aop_dir,
5214                         AOP(right)->aopu.aop_dir);
5215                 pic14_emitcode("setc","");
5216                 
5217         } else {
5218                 tlbl = newiTempLabel(NULL);
5219                 pic14_toBoolean(left);
5220                 emitSKPZ;
5221                 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5222                 pic14_toBoolean(right);
5223                 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5224                 
5225                 pic14_outBitAcc(result);
5226         }
5227         
5228         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5229         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5230         freeAsmop(result,NULL,ic,TRUE);            
5231 }
5232
5233 /*-----------------------------------------------------------------*/
5234 /* isLiteralBit - test if lit == 2^n                               */
5235 /*-----------------------------------------------------------------*/
5236 static int isLiteralBit(unsigned long lit)
5237 {
5238         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5239                 0x100L,0x200L,0x400L,0x800L,
5240                 0x1000L,0x2000L,0x4000L,0x8000L,
5241                 0x10000L,0x20000L,0x40000L,0x80000L,
5242                 0x100000L,0x200000L,0x400000L,0x800000L,
5243                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5244                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5245         int idx;
5246         
5247         FENTRY;
5248         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5249         for(idx = 0; idx < 32; idx++)
5250                 if(lit == pw[idx])
5251                         return idx+1;
5252                 return 0;
5253 }
5254
5255 /*-----------------------------------------------------------------*/
5256 /* continueIfTrue -                                                */
5257 /*-----------------------------------------------------------------*/
5258 static void continueIfTrue (iCode *ic)
5259 {
5260         FENTRY;
5261         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5262         if(IC_TRUE(ic))
5263                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5264         ic->generated = 1;
5265 }
5266
5267 /*-----------------------------------------------------------------*/
5268 /* jmpIfTrue -                                                     */
5269 /*-----------------------------------------------------------------*/
5270 static void jumpIfTrue (iCode *ic)
5271 {
5272         FENTRY;
5273         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5274         if(!IC_TRUE(ic))
5275                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5276         ic->generated = 1;
5277 }
5278
5279 /*-----------------------------------------------------------------*/
5280 /* jmpTrueOrFalse -                                                */
5281 /*-----------------------------------------------------------------*/
5282 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5283 {
5284         FENTRY;
5285         // ugly but optimized by peephole
5286         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5287         if(IC_TRUE(ic)){
5288                 symbol *nlbl = newiTempLabel(NULL);
5289                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5290                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5291                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5292                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5293         }
5294         else{
5295                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5296                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5297         }
5298         ic->generated = 1;
5299 }
5300
5301 /*-----------------------------------------------------------------*/
5302 /* genAnd  - code for and                                          */
5303 /*-----------------------------------------------------------------*/
5304 static void genAnd (iCode *ic, iCode *ifx)
5305 {
5306         operand *left, *right, *result;
5307         int size, offset=0;  
5308         unsigned long lit = 0L;
5309         int bytelit = 0;
5310         resolvedIfx rIfx;
5311         
5312         FENTRY;
5313         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5314         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5315         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5316         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5317         
5318         resolveIfx(&rIfx,ifx);
5319         
5320         /* if left is a literal & right is not then exchange them */
5321         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5322                 AOP_NEEDSACC(left)) {
5323                 operand *tmp = right ;
5324                 right = left;
5325                 left = tmp;
5326         }
5327         
5328         /* if result = right then exchange them */
5329         if(pic14_sameRegs(AOP(result),AOP(right))){
5330                 operand *tmp = right ;
5331                 right = left;
5332                 left = tmp;
5333         }
5334         
5335         /* if right is bit then exchange them */
5336         if (AOP_TYPE(right) == AOP_CRY &&
5337                 AOP_TYPE(left) != AOP_CRY){
5338                 operand *tmp = right ;
5339                 right = left;
5340                 left = tmp;
5341         }
5342         if(AOP_TYPE(right) == AOP_LIT)
5343                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5344         
5345         size = AOP_SIZE(result);
5346         
5347         DEBUGpic14_AopType(__LINE__,left,right,result);
5348         
5349         // if(bit & yy)
5350         // result = bit & yy;
5351         if (AOP_TYPE(left) == AOP_CRY){
5352                 // c = bit & literal;
5353                 if(AOP_TYPE(right) == AOP_LIT){
5354                         if(lit & 1) {
5355                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5356                                         // no change
5357                                         goto release;
5358                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5359                         } else {
5360                                 // bit(result) = 0;
5361                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5362                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5363                                         goto release;
5364                                 }
5365                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5366                                         jumpIfTrue(ifx);
5367                                         goto release;
5368                                 }
5369                                 pic14_emitcode("clr","c");
5370                         }
5371                 } else {
5372                         if (AOP_TYPE(right) == AOP_CRY){
5373                                 // c = bit & bit;
5374                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5375                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5376                         } else {
5377                                 // c = bit & val;
5378                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5379                                 // c = lsb
5380                                 pic14_emitcode("rrc","a");
5381                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5382                         }
5383                 }
5384                 // bit = c
5385                 // val = c
5386                 if(size)
5387                         pic14_outBitC(result);
5388                 // if(bit & ...)
5389                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5390                         genIfxJump(ifx, "c");           
5391                 goto release ;
5392         }
5393         
5394         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5395         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5396         if((AOP_TYPE(right) == AOP_LIT) &&
5397                 (AOP_TYPE(result) == AOP_CRY) &&
5398                 (AOP_TYPE(left) != AOP_CRY)){
5399                 int posbit = isLiteralBit(lit);
5400                 /* left &  2^n */
5401                 if(posbit){
5402                         posbit--;
5403                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5404                         // bit = left & 2^n
5405                         if(size)
5406                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5407                         // if(left &  2^n)
5408                         else{
5409                                 if(ifx){
5410                                         int offset = 0;
5411                                         while (posbit > 7) {
5412                                                 posbit -= 8;
5413                                                 offset++;
5414                                         }
5415                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5416                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5417                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5418                                         
5419                                         ifx->generated = 1;
5420                                 }
5421                                 goto release;
5422                         }
5423                 } else {
5424                         symbol *tlbl = newiTempLabel(NULL);
5425                         int sizel = AOP_SIZE(left);
5426                         if(size)
5427                                 pic14_emitcode("setb","c");
5428                         while(sizel--){
5429                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5430                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5431                                         // byte ==  2^n ?
5432                                         if((posbit = isLiteralBit(bytelit)) != 0)
5433                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5434                                         else{
5435                                                 if(bytelit != 0x0FFL)
5436                                                         pic14_emitcode("anl","a,%s",
5437                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5438                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5439                                         }
5440                                 }
5441                                 offset++;
5442                         }
5443                         // bit = left & literal
5444                         if(size){
5445                                 pic14_emitcode("clr","c");
5446                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5447                         }
5448                         // if(left & literal)
5449                         else{
5450                                 if(ifx)
5451                                         jmpTrueOrFalse(ifx, tlbl);
5452                                 goto release ;
5453                         }
5454                 }
5455                 pic14_outBitC(result);
5456                 goto release ;
5457         }
5458         
5459         /* if left is same as result */
5460         if(pic14_sameRegs(AOP(result),AOP(left))){
5461                 int know_W = -1;
5462                 for(;size--; offset++,lit>>=8) {
5463                         if(AOP_TYPE(right) == AOP_LIT){
5464                                 switch(lit & 0xff) {
5465                                 case 0x00:
5466                                         /*  and'ing with 0 has clears the result */
5467                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5468                                         break;
5469                                 case 0xff:
5470                                         /* and'ing with 0xff is a nop when the result and left are the same */
5471                                         break;
5472                                         
5473                                 default:
5474                                         {
5475                                                 int p = my_powof2( (~lit) & 0xff );
5476                                                 if(p>=0) {
5477                                                         /* only one bit is set in the literal, so use a bcf instruction */
5478                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5479                                                         
5480                                                 } else {
5481                                                         if(know_W != (int)(lit&0xff))
5482                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5483                                                         know_W = lit &0xff;
5484                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5485                                                 }
5486                                         }    
5487                                 }
5488                         } else {
5489                                 if (AOP_TYPE(left) == AOP_ACC) {
5490                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5491                                 } else {        
5492                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5493                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5494                                         
5495                                 }
5496                         }
5497                 }
5498                 
5499         } else {
5500                 // left & result in different registers
5501                 if(AOP_TYPE(result) == AOP_CRY){
5502                         // result = bit
5503                         // if(size), result in bit
5504                         // if(!size && ifx), conditional oper: if(left & right)
5505                         symbol *tlbl = newiTempLabel(NULL);
5506                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5507                         if(size)
5508                                 pic14_emitcode("setb","c");
5509                         while(sizer--){
5510                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5511                                 pic14_emitcode("anl","a,%s",
5512                                         aopGet(AOP(left),offset,FALSE,FALSE));
5513                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5514                                 offset++;
5515                         }
5516                         if(size){
5517                                 CLRC;
5518                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5519                                 pic14_outBitC(result);
5520                         } else if(ifx)
5521                                 jmpTrueOrFalse(ifx, tlbl);
5522                 } else {
5523                         for(;(size--);offset++) {
5524                                 // normal case
5525                                 // result = left & right
5526                                 if(AOP_TYPE(right) == AOP_LIT){
5527                                         int t = (lit >> (offset*8)) & 0x0FFL;
5528                                         switch(t) { 
5529                                         case 0x00:
5530                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5531                                                 break;
5532                                         case 0xff:
5533                                                 if(AOP_TYPE(left) != AOP_ACC) {
5534                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5535                                                 }
5536                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5537                                                 break;
5538                                         default:
5539                                                 if(AOP_TYPE(left) == AOP_ACC) {
5540                                                         emitpcode(POC_ANDLW, popGetLit(t));
5541                                                 } else {
5542                                                         emitpcode(POC_MOVLW, popGetLit(t));
5543                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5544                                                 }
5545                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5546                                         }
5547                                         continue;
5548                                 }
5549                                 
5550                                 if (AOP_TYPE(left) == AOP_ACC) {
5551                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5552                                 } else {
5553                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5554                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5555                                 }
5556                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5557                         }
5558                 }
5559         }
5560         
5561 release :
5562         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5563         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5564         freeAsmop(result,NULL,ic,TRUE);     
5565 }
5566
5567 /*-----------------------------------------------------------------*/
5568 /* genOr  - code for or                                            */
5569 /*-----------------------------------------------------------------*/
5570 static void genOr (iCode *ic, iCode *ifx)
5571 {
5572         operand *left, *right, *result;
5573         int size, offset=0;
5574         unsigned long lit = 0L;
5575         
5576         FENTRY;
5577         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5578         
5579         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5580         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5581         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5582         
5583         DEBUGpic14_AopType(__LINE__,left,right,result);
5584         
5585         /* if left is a literal & right is not then exchange them */
5586         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5587                 AOP_NEEDSACC(left)) {
5588                 operand *tmp = right ;
5589                 right = left;
5590                 left = tmp;
5591         }
5592         
5593         /* if result = right then exchange them */
5594         if(pic14_sameRegs(AOP(result),AOP(right))){
5595                 operand *tmp = right ;
5596                 right = left;
5597                 left = tmp;
5598         }
5599         
5600         /* if right is bit then exchange them */
5601         if (AOP_TYPE(right) == AOP_CRY &&
5602                 AOP_TYPE(left) != AOP_CRY){
5603                 operand *tmp = right ;
5604                 right = left;
5605                 left = tmp;
5606         }
5607         
5608         DEBUGpic14_AopType(__LINE__,left,right,result);
5609         
5610         if(AOP_TYPE(right) == AOP_LIT)
5611                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5612         
5613         size = AOP_SIZE(result);
5614         
5615         // if(bit | yy)
5616         // xx = bit | yy;
5617         if (AOP_TYPE(left) == AOP_CRY){
5618                 if(AOP_TYPE(right) == AOP_LIT){
5619                         // c = bit & literal;
5620                         if(lit){
5621                                 // lit != 0 => result = 1
5622                                 if(AOP_TYPE(result) == AOP_CRY){
5623                                         if(size)
5624                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5625                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5626                                         //   AOP(result)->aopu.aop_dir,
5627                                         //   AOP(result)->aopu.aop_dir);
5628                                         else if(ifx)
5629                                                 continueIfTrue(ifx);
5630                                         goto release;
5631                                 }
5632                         } else {
5633                                 // lit == 0 => result = left
5634                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5635                                         goto release;
5636                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5637                         }
5638                 } else {
5639                         if (AOP_TYPE(right) == AOP_CRY){
5640                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5641                                         // c = bit | bit;
5642                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5643                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5644                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5645                                         
5646                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5647                                                 AOP(result)->aopu.aop_dir,
5648                                                 AOP(result)->aopu.aop_dir);
5649                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5650                                                 AOP(right)->aopu.aop_dir,
5651                                                 AOP(right)->aopu.aop_dir);
5652                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5653                                                 AOP(result)->aopu.aop_dir,
5654                                                 AOP(result)->aopu.aop_dir);
5655                                 } else {
5656                                         if( AOP_TYPE(result) == AOP_ACC) {
5657                                                 emitpcode(POC_MOVLW, popGetLit(0));
5658                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5659                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5660                                                 emitpcode(POC_MOVLW, popGetLit(1));
5661                                                 
5662                                         } else {
5663                                                 
5664                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5665                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5666                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5667                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5668                                                 
5669                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5670                                                         AOP(result)->aopu.aop_dir,
5671                                                         AOP(result)->aopu.aop_dir);
5672                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5673                                                         AOP(right)->aopu.aop_dir,
5674                                                         AOP(right)->aopu.aop_dir);
5675                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5676                                                         AOP(left)->aopu.aop_dir,
5677                                                         AOP(left)->aopu.aop_dir);
5678                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5679                                                         AOP(result)->aopu.aop_dir,
5680                                                         AOP(result)->aopu.aop_dir);
5681                                         }
5682                                 }
5683                         } else {
5684                                 // c = bit | val;
5685                                 symbol *tlbl = newiTempLabel(NULL);
5686                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5687                                 
5688                                 
5689                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5690                                 if( AOP_TYPE(right) == AOP_ACC) {
5691                                         emitpcode(POC_IORLW, popGetLit(0));
5692                                         emitSKPNZ;
5693                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5694                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5695                                 }
5696                                 
5697                                 
5698                                 
5699                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5700                                         pic14_emitcode(";XXX setb","c");
5701                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5702                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5703                                 pic14_toBoolean(right);
5704                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5705                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5706                                         jmpTrueOrFalse(ifx, tlbl);
5707                                         goto release;
5708                                 } else {
5709                                         CLRC;
5710                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5711                                 }
5712                         }
5713                 }
5714                 // bit = c
5715                 // val = c
5716                 if(size)
5717                         pic14_outBitC(result);
5718                 // if(bit | ...)
5719                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5720                         genIfxJump(ifx, "c");           
5721                 goto release ;
5722         }
5723
5724         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5725         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5726         if((AOP_TYPE(right) == AOP_LIT) &&
5727           (AOP_TYPE(result) == AOP_CRY) &&
5728           (AOP_TYPE(left) != AOP_CRY)){
5729                 if(lit){
5730                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5731                         // result = 1
5732                         if(size)
5733                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5734                         else 
5735                                 continueIfTrue(ifx);
5736                         goto release;
5737                 } else {
5738                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5739                         // lit = 0, result = boolean(left)
5740                         if(size)
5741                                 pic14_emitcode(";XXX setb","c");
5742                         pic14_toBoolean(right);
5743                         if(size){
5744                                 symbol *tlbl = newiTempLabel(NULL);
5745                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5746                                 CLRC;
5747                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5748                         } else {
5749                                 genIfxJump (ifx,"a");
5750                                 goto release;
5751                         }
5752                 }
5753                 pic14_outBitC(result);
5754                 goto release ;
5755         }
5756
5757         /* if left is same as result */
5758         if(pic14_sameRegs(AOP(result),AOP(left))){
5759                 int know_W = -1;
5760                 for(;size--; offset++,lit>>=8) {
5761                         if(AOP_TYPE(right) == AOP_LIT){
5762                                 if((lit & 0xff) == 0)
5763                                         /*  or'ing with 0 has no effect */
5764                                         continue;
5765                                 else {
5766                                         int p = my_powof2(lit & 0xff);
5767                                         if(p>=0) {
5768                                                 /* only one bit is set in the literal, so use a bsf instruction */
5769                                                 emitpcode(POC_BSF,
5770                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5771                                         } else {
5772                                                 if(know_W != (int)(lit & 0xff))
5773                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5774                                                 know_W = lit & 0xff;
5775                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5776                                         }
5777                                         
5778                                 }
5779                         } else {
5780                                 if (AOP_TYPE(left) == AOP_ACC) {
5781                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5782                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5783                                 } else {        
5784                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5785                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5786                                         
5787                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5788                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5789                                         
5790                                 }
5791                         }
5792                 }
5793         } else {
5794                 // left & result in different registers
5795                 if(AOP_TYPE(result) == AOP_CRY){
5796                         // result = bit
5797                         // if(size), result in bit
5798                         // if(!size && ifx), conditional oper: if(left | right)
5799                         symbol *tlbl = newiTempLabel(NULL);
5800                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5801                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5802                         
5803                         
5804                         if(size)
5805                                 pic14_emitcode(";XXX setb","c");
5806                         while(sizer--){
5807                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5808                                 pic14_emitcode(";XXX orl","a,%s",
5809                                         aopGet(AOP(left),offset,FALSE,FALSE));
5810                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5811                                 offset++;
5812                         }
5813                         if(size){
5814                                 CLRC;
5815                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5816                                 pic14_outBitC(result);
5817                         } else if(ifx)
5818                                 jmpTrueOrFalse(ifx, tlbl);
5819                 } else for(;(size--);offset++){
5820                         // normal case
5821                         // result = left | right
5822                         if(AOP_TYPE(right) == AOP_LIT){
5823                                 int t = (lit >> (offset*8)) & 0x0FFL;
5824                                 switch(t) { 
5825                                 case 0x00:
5826                                         if (AOP_TYPE(left) != AOP_ACC) {
5827                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5828                                         }
5829                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5830                                         
5831                                         break;
5832                                 default:
5833                                         if (AOP_TYPE(left) == AOP_ACC) {
5834                                                 emitpcode(POC_IORLW,  popGetLit(t));
5835                                         } else {
5836                                                 emitpcode(POC_MOVLW,  popGetLit(t));
5837                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5838                                         }
5839                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
5840                                 }
5841                                 continue;
5842                         }
5843                         
5844                         // faster than result <- left, anl result,right
5845                         // and better if result is SFR
5846                         if (AOP_TYPE(left) == AOP_ACC) {
5847                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5848                         } else {
5849                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5850                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5851                         }
5852                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5853                 }
5854         }
5855
5856 release :
5857         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5858         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5859         freeAsmop(result,NULL,ic,TRUE);     
5860 }
5861
5862 /*-----------------------------------------------------------------*/
5863 /* genXor - code for xclusive or                                   */
5864 /*-----------------------------------------------------------------*/
5865 static void genXor (iCode *ic, iCode *ifx)
5866 {
5867         operand *left, *right, *result;
5868         int size, offset=0;
5869         unsigned long lit = 0L;
5870         
5871         FENTRY;
5872         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5873         
5874         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5875         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5876         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5877         
5878         /* if left is a literal & right is not ||
5879         if left needs acc & right does not */
5880         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5881                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5882                 operand *tmp = right ;
5883                 right = left;
5884                 left = tmp;
5885         }
5886         
5887         /* if result = right then exchange them */
5888         if(pic14_sameRegs(AOP(result),AOP(right))){
5889                 operand *tmp = right ;
5890                 right = left;
5891                 left = tmp;
5892         }
5893         
5894         /* if right is bit then exchange them */
5895         if (AOP_TYPE(right) == AOP_CRY &&
5896                 AOP_TYPE(left) != AOP_CRY){
5897                 operand *tmp = right ;
5898                 right = left;
5899                 left = tmp;
5900         }
5901         if(AOP_TYPE(right) == AOP_LIT)
5902                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5903         
5904         size = AOP_SIZE(result);
5905         
5906         // if(bit ^ yy)
5907         // xx = bit ^ yy;
5908         if (AOP_TYPE(left) == AOP_CRY){
5909                 if(AOP_TYPE(right) == AOP_LIT){
5910                         // c = bit & literal;
5911                         if(lit>>1){
5912                                 // lit>>1  != 0 => result = 1
5913                                 if(AOP_TYPE(result) == AOP_CRY){
5914                                         if(size)
5915                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5916                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5917                                         else if(ifx)
5918                                                 continueIfTrue(ifx);
5919                                         goto release;
5920                                 }
5921                                 pic14_emitcode("setb","c");
5922                         } else{
5923                                 // lit == (0 or 1)
5924                                 if(lit == 0){
5925                                         // lit == 0, result = left
5926                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5927                                                 goto release;
5928                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5929                                 } else{
5930                                         // lit == 1, result = not(left)
5931                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
5932                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5933                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5934                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5935                                                 goto release;
5936                                         } else {
5937                                                 assert ( !"incomplete genXor" );
5938                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5939                                                 pic14_emitcode("cpl","c");
5940                                         }
5941                                 }
5942                         }
5943                         
5944                 } else {
5945                         // right != literal
5946                         symbol *tlbl = newiTempLabel(NULL);
5947                         if (AOP_TYPE(right) == AOP_CRY){
5948                                 // c = bit ^ bit;
5949                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5950                         }
5951                         else{
5952                                 int sizer = AOP_SIZE(right);
5953                                 // c = bit ^ val
5954                                 // if val>>1 != 0, result = 1
5955                                 pic14_emitcode("setb","c");
5956                                 while(sizer){
5957                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5958                                         if(sizer == 1)
5959                                                 // test the msb of the lsb
5960                                                 pic14_emitcode("anl","a,#0xfe");
5961                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5962                                         sizer--;
5963                                 }
5964                                 // val = (0,1)
5965                                 pic14_emitcode("rrc","a");
5966                         }
5967                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5968                         pic14_emitcode("cpl","c");
5969                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5970                 }
5971                 // bit = c
5972                 // val = c
5973                 if(size)
5974                         pic14_outBitC(result);
5975                 // if(bit | ...)
5976                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5977                         genIfxJump(ifx, "c");           
5978                 goto release ;
5979         }
5980         
5981         if(pic14_sameRegs(AOP(result),AOP(left))){
5982                 /* if left is same as result */
5983                 for(;size--; offset++) {
5984                         if(AOP_TYPE(right) == AOP_LIT){
5985                                 int t  = (lit >> (offset*8)) & 0x0FFL;
5986                                 if(t == 0x00L)
5987                                         continue;
5988                                 else
5989                                         if (IS_AOP_PREG(left)) {
5990                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5991                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5992                                                 aopPut(AOP(result),"a",offset);
5993                                         } else {
5994                                                 emitpcode(POC_MOVLW, popGetLit(t));
5995                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
5996                                                 pic14_emitcode("xrl","%s,%s",
5997                                                         aopGet(AOP(left),offset,FALSE,TRUE),
5998                                                         aopGet(AOP(right),offset,FALSE,FALSE));
5999                                         }
6000                         } else {
6001                                 if (AOP_TYPE(left) == AOP_ACC)
6002                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6003                                 else {
6004                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6005                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6006                                         /*
6007                                         if (IS_AOP_PREG(left)) {
6008                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6009                                         aopPut(AOP(result),"a",offset);
6010                                         } else
6011                                         pic14_emitcode("xrl","%s,a",
6012                                         aopGet(AOP(left),offset,FALSE,TRUE));
6013                                         */
6014                                 }
6015                         }
6016                 }
6017         } else {
6018                 // left & result in different registers
6019                 if(AOP_TYPE(result) == AOP_CRY){
6020                         // result = bit
6021                         // if(size), result in bit
6022                         // if(!size && ifx), conditional oper: if(left ^ right)
6023                         symbol *tlbl = newiTempLabel(NULL);
6024                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6025                         if(size)
6026                                 pic14_emitcode("setb","c");
6027                         while(sizer--){
6028                                 if((AOP_TYPE(right) == AOP_LIT) &&
6029                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6030                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6031                                 } else {
6032                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6033                                         pic14_emitcode("xrl","a,%s",
6034                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6035                                 }
6036                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6037                                 offset++;
6038                         }
6039                         if(size){
6040                                 CLRC;
6041                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6042                                 pic14_outBitC(result);
6043                         } else if(ifx)
6044                                 jmpTrueOrFalse(ifx, tlbl);
6045                 } else for(;(size--);offset++){
6046                         // normal case
6047                         // result = left & right
6048                         if(AOP_TYPE(right) == AOP_LIT){
6049                                 int t = (lit >> (offset*8)) & 0x0FFL;
6050                                 switch(t) { 
6051                                 case 0x00:
6052                                         if (AOP_TYPE(left) != AOP_ACC) {
6053                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6054                                         }
6055                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6056                                         pic14_emitcode("movf","%s,w",
6057                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6058                                         pic14_emitcode("movwf","%s",
6059                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6060                                         break;
6061                                 case 0xff:
6062                                         if (AOP_TYPE(left) == AOP_ACC) {
6063                                                 emitpcode(POC_XORLW, popGetLit(t));
6064                                         } else {
6065                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6066                                         }
6067                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6068                                         break;
6069                                 default:
6070                                         if (AOP_TYPE(left) == AOP_ACC) {
6071                                                 emitpcode(POC_XORLW, popGetLit(t));
6072                                         } else {
6073                                                 emitpcode(POC_MOVLW, popGetLit(t));
6074                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6075                                         }
6076                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6077                                         pic14_emitcode("movlw","0x%x",t);
6078                                         pic14_emitcode("xorwf","%s,w",
6079                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6080                                         pic14_emitcode("movwf","%s",
6081                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6082                                         
6083                                 }
6084                                 continue;
6085                         }
6086                         
6087                         // faster than result <- left, anl result,right
6088                         // and better if result is SFR
6089                         if (AOP_TYPE(left) == AOP_ACC) {
6090                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6091                         } else {
6092                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6093                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6094                         }
6095                         if ( AOP_TYPE(result) != AOP_ACC){
6096                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6097                         }
6098                 }
6099         }
6100         
6101 release :
6102         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6103         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6104         freeAsmop(result,NULL,ic,TRUE);     
6105 }
6106
6107 /*-----------------------------------------------------------------*/
6108 /* genInline - write the inline code out                           */
6109 /*-----------------------------------------------------------------*/
6110 static void genInline (iCode *ic)
6111 {
6112   char *buffer, *bp, *bp1;
6113
6114   FENTRY;
6115   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6116
6117   _G.inLine += (!options.asmpeep);
6118
6119   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6120   strcpy(buffer,IC_INLINE(ic));
6121
6122   /* emit each line as a code */
6123   while (*bp) {
6124     if (*bp == '\n') {
6125       *bp++ = '\0';
6126       
6127       if(*bp1)
6128         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6129       bp1 = bp;
6130     } else {
6131       if (*bp == ':') {
6132         bp++;
6133         *bp = '\0';
6134         bp++;
6135
6136         /* print label, use this special format with NULL directive
6137          * to denote that the argument should not be indented with tab */
6138         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6139
6140         bp1 = bp;
6141       } else
6142         bp++;
6143     }
6144   }
6145   if ((bp1 != bp) && *bp1)
6146     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6147
6148   Safe_free(buffer);
6149
6150   _G.inLine -= (!options.asmpeep);
6151 }
6152
6153 /*-----------------------------------------------------------------*/
6154 /* genRRC - rotate right with carry                                */
6155 /*-----------------------------------------------------------------*/
6156 static void genRRC (iCode *ic)
6157 {
6158         operand *left , *result ;
6159         int size, offset = 0, same;
6160         
6161         FENTRY;
6162         /* rotate right with carry */
6163         left = IC_LEFT(ic);
6164         result=IC_RESULT(ic);
6165         aopOp (left,ic,FALSE);
6166         aopOp (result,ic,FALSE);
6167         
6168         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6169         
6170         same = pic14_sameRegs(AOP(result),AOP(left));
6171         
6172         size = AOP_SIZE(result);    
6173         
6174         /* get the lsb and put it into the carry */
6175         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6176         
6177         offset = 0 ;
6178         
6179         while(size--) {
6180                 
6181                 if(same) {
6182                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6183                 } else {
6184                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6185                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6186                 }
6187                 
6188                 offset++;
6189         }
6190         
6191         freeAsmop(left,NULL,ic,TRUE);
6192         freeAsmop(result,NULL,ic,TRUE);
6193 }
6194
6195 /*-----------------------------------------------------------------*/
6196 /* genRLC - generate code for rotate left with carry               */
6197 /*-----------------------------------------------------------------*/
6198 static void genRLC (iCode *ic)
6199 {    
6200         operand *left , *result ;
6201         int size, offset = 0;
6202         int same;
6203         
6204         FENTRY;
6205         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6206         /* rotate right with carry */
6207         left = IC_LEFT(ic);
6208         result=IC_RESULT(ic);
6209         aopOp (left,ic,FALSE);
6210         aopOp (result,ic,FALSE);
6211         
6212         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6213         
6214         same = pic14_sameRegs(AOP(result),AOP(left));
6215         
6216         /* move it to the result */
6217         size = AOP_SIZE(result);    
6218         
6219         /* get the msb and put it into the carry */
6220         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6221         
6222         offset = 0 ;
6223         
6224         while(size--) {
6225                 
6226                 if(same) {
6227                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6228                 } else {
6229                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6230                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6231                 }
6232                 
6233                 offset++;
6234         }
6235         
6236         
6237         freeAsmop(left,NULL,ic,TRUE);
6238         freeAsmop(result,NULL,ic,TRUE);
6239 }
6240
6241 /*-----------------------------------------------------------------*/
6242 /* genGetHbit - generates code get highest order bit               */
6243 /*-----------------------------------------------------------------*/
6244 static void genGetHbit (iCode *ic)
6245 {
6246         operand *left, *result;
6247         left = IC_LEFT(ic);
6248         result=IC_RESULT(ic);
6249         aopOp (left,ic,FALSE);
6250         aopOp (result,ic,FALSE);
6251         
6252         FENTRY;
6253         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6254         /* get the highest order byte into a */
6255         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6256         if(AOP_TYPE(result) == AOP_CRY){
6257                 pic14_emitcode("rlc","a");
6258                 pic14_outBitC(result);
6259         }
6260         else{
6261                 pic14_emitcode("rl","a");
6262                 pic14_emitcode("anl","a,#0x01");
6263                 pic14_outAcc(result);
6264         }
6265         
6266         
6267         freeAsmop(left,NULL,ic,TRUE);
6268         freeAsmop(result,NULL,ic,TRUE);
6269 }
6270
6271 /*-----------------------------------------------------------------*/
6272 /* AccRol - rotate left accumulator by known count                 */
6273 /*-----------------------------------------------------------------*/
6274 static void AccRol (operand *op,int offset,int shCount)
6275 {
6276         FENTRY;
6277         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6278         shCount &= 0x0007;              // shCount : 0..7
6279         switch(shCount){
6280         case 0 :
6281                 break;
6282         case 1 :
6283                 pic14_emitcode("rl","a");
6284                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6285                 break;
6286         case 2 :
6287                 pic14_emitcode("rl","a");
6288                 pic14_emitcode("rl","a");
6289                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6290                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6291                 break;
6292         case 3 :
6293                 pic14_emitcode("swap","a");
6294                 pic14_emitcode("rr","a");
6295                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6296                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6297                 break;
6298         case 4 :
6299                 pic14_emitcode("swap","a");
6300                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6301                 break;
6302         case 5 :
6303                 pic14_emitcode("swap","a");
6304                 pic14_emitcode("rl","a");
6305                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6306                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6307                 break;
6308         case 6 :
6309                 pic14_emitcode("rr","a");
6310                 pic14_emitcode("rr","a");
6311                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6312                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6313                 break;
6314         case 7 :
6315                 pic14_emitcode("rr","a");
6316                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6317                 break;
6318         }
6319 }
6320
6321 /*-----------------------------------------------------------------*/
6322 /* AccLsh - left shift accumulator by known count                  */
6323 /*-----------------------------------------------------------------*/
6324 static void AccLsh (operand *op,int offset,int shCount)
6325 {
6326         FENTRY;
6327         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6328         if(shCount != 0) {
6329                 if (shCount == 1)
6330                 {
6331                         emitCLRC;
6332                         emitpcode (POC_RLF, popGet (AOP(op), 0));
6333                 } else {
6334                         /* rotate left accumulator */
6335                         AccRol(op,offset,shCount);
6336                         /* and kill the lower order bits */
6337                         emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
6338                         emitpcode (POC_ANDWF, popGet (AOP(op),0));
6339                 }
6340         }
6341 }
6342
6343 /*-----------------------------------------------------------------*/
6344 /* AccRsh - right shift accumulator by known count                 */
6345 /*-----------------------------------------------------------------*/
6346 static void AccRsh (operand *op,int offset,int shCount)
6347 {
6348         FENTRY;
6349         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6350         if(shCount != 0){
6351                 if(shCount == 1){
6352                         emitCLRC;
6353                         emitpcode (POC_RRF, popGet (AOP(op), 0));
6354                 } else {
6355                         /* rotate right accumulator */
6356                         AccRol(op,offset,8 - shCount);
6357                         /* and kill the higher order bits */
6358                         emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
6359                         emitpcode (POC_ANDWF, popGet (AOP(op),0));
6360                 }
6361         }
6362 }
6363
6364 #if 0
6365 /*-----------------------------------------------------------------*/
6366 /* AccSRsh - signed right shift accumulator by known count                 */
6367 /*-----------------------------------------------------------------*/
6368 static void AccSRsh (int shCount)
6369 {
6370         symbol *tlbl ;
6371         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6372         if(shCount != 0){
6373                 if(shCount == 1){
6374                         pic14_emitcode("mov","c,acc.7");
6375                         pic14_emitcode("rrc","a");
6376                 } else if(shCount == 2){
6377                         pic14_emitcode("mov","c,acc.7");
6378                         pic14_emitcode("rrc","a");
6379                         pic14_emitcode("mov","c,acc.7");
6380                         pic14_emitcode("rrc","a");
6381                 } else {
6382                         tlbl = newiTempLabel(NULL);
6383                         /* rotate right accumulator */
6384                         AccRol(8 - shCount);
6385                         /* and kill the higher order bits */
6386                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6387                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6388                         pic14_emitcode("orl","a,#0x%02x",
6389                                 (unsigned char)~SRMask[shCount]);
6390                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6391                 }
6392         }
6393 }
6394
6395 /*-----------------------------------------------------------------*/
6396 /* shiftR1Left2Result - shift right one byte from left to result   */
6397 /*-----------------------------------------------------------------*/
6398 static void shiftR1Left2ResultSigned (operand *left, int offl,
6399                                                                           operand *result, int offr,
6400                                                                           int shCount)
6401 {
6402         int same;
6403         
6404         FENTRY;
6405         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6406         
6407         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6408         
6409         switch(shCount) {
6410         case 1:
6411                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6412                 if(same) 
6413                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6414                 else {
6415                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6416                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6417                 }
6418                 
6419                 break;
6420         case 2:
6421                 
6422                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6423                 if(same) 
6424                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6425                 else {
6426                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6427                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6428                 }
6429                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6430                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6431                 
6432                 break;
6433                 
6434         case 3:
6435                 if(same)
6436                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6437                 else {
6438                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6439                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6440                 }
6441                 
6442                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6443                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6444                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6445                 
6446                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6447                 emitpcode(POC_IORLW, popGetLit(0xe0));
6448                 
6449                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6450                 break;
6451                 
6452         case 4:
6453                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6454                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6455                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6456                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6457                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6458                 break;
6459         case 5:
6460                 if(same) {
6461                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6462                 } else {
6463                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6464                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6465                 }
6466                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6467                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6468                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6469                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6470                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6471                 break;
6472                 
6473         case 6:
6474                 if(same) {
6475                         emitpcode(POC_MOVLW, popGetLit(0x00));
6476                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6477                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6478                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6479                         emitpcode(POC_IORLW, popGetLit(0x01));
6480                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6481                 } else {
6482                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6483                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6484                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6485                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6486                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6487                 }
6488                 break;
6489                 
6490         case 7:
6491                 if(same) {
6492                         emitpcode(POC_MOVLW, popGetLit(0x00));
6493                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6494                         emitpcode(POC_MOVLW, popGetLit(0xff));
6495                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6496                 } else {
6497                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6498                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6499                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6500                 }
6501                 
6502         default:
6503                 break;
6504         }
6505 }
6506
6507 /*-----------------------------------------------------------------*/
6508 /* shiftR1Left2Result - shift right one byte from left to result   */
6509 /*-----------------------------------------------------------------*/
6510 static void shiftR1Left2Result (operand *left, int offl,
6511                                                                 operand *result, int offr,
6512                                                                 int shCount, int sign)
6513 {
6514         int same;
6515         
6516         FENTRY;
6517         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6518         
6519         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6520         
6521         /* Copy the msb into the carry if signed. */
6522         if(sign) {
6523                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6524                 return;
6525         }
6526         
6527         
6528         
6529         switch(shCount) {
6530         case 1:
6531                 emitCLRC;
6532                 if(same) 
6533                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6534                 else {
6535                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6536                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6537                 }
6538                 break;
6539         case 2:
6540                 emitCLRC;
6541                 if(same) {
6542                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6543                 } else {
6544                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6545                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6546                 }
6547                 emitCLRC;
6548                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6549                 
6550                 break;
6551         case 3:
6552                 if(same)
6553                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6554                 else {
6555                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6556                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6557                 }
6558                 
6559                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6560                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6561                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6562                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6563                 break;
6564                 
6565         case 4:
6566                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6567                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6568                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6569                 break;
6570                 
6571         case 5:
6572                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6573                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6574                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6575                 emitCLRC;
6576                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6577                 
6578                 break;
6579         case 6:
6580                 
6581                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6582                 emitpcode(POC_ANDLW, popGetLit(0x80));
6583                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6584                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6585                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6586                 break;
6587                 
6588         case 7:
6589                 
6590                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6591                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6592                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6593                 
6594                 break;
6595                 
6596         default:
6597                 break;
6598         }
6599 }
6600
6601 /*-----------------------------------------------------------------*/
6602 /* shiftL1Left2Result - shift left one byte from left to result    */
6603 /*-----------------------------------------------------------------*/
6604 static void shiftL1Left2Result (operand *left, int offl,
6605                                                                 operand *result, int offr, int shCount)
6606 {
6607         int same;
6608         
6609         //    char *l;
6610         FENTRY;
6611         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6612         
6613         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6614         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6615         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6616         //    MOVA(l);
6617         /* shift left accumulator */
6618         //AccLsh(shCount); // don't comment out just yet...
6619         //    aopPut(AOP(result),"a",offr);
6620         
6621         switch(shCount) {
6622         case 1:
6623                 /* Shift left 1 bit position */
6624                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6625                 if(same) {
6626                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6627                 } else {
6628                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6629                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6630                 }
6631                 break;
6632         case 2:
6633                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6634                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6635                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6636                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6637                 break;
6638         case 3:
6639                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6640                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6641                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6642                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6643                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6644                 break;
6645         case 4:
6646                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6647                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6648                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6649                 break;
6650         case 5:
6651                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6652                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6653                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6654                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6655                 break;
6656         case 6:
6657                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6658                 emitpcode(POC_ANDLW, popGetLit(0x30));
6659                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6660                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6661                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6662                 break;
6663         case 7:
6664                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6665                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6666                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6667                 break;
6668                 
6669         default:
6670                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6671         }
6672         
6673 }
6674 #endif
6675
6676 /*-----------------------------------------------------------------*/
6677 /* movLeft2Result - move byte from left to result                  */
6678 /*-----------------------------------------------------------------*/
6679 static void movLeft2Result (operand *left, int offl,
6680                                                         operand *result, int offr)
6681 {
6682         char *l;
6683         FENTRY;
6684         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6685         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6686                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6687                 
6688                 if (*l == '@' && (IS_AOP_PREG(result))) {
6689                         pic14_emitcode("mov","a,%s",l);
6690                         aopPut(AOP(result),"a",offr);
6691                 } else {
6692                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6693                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6694                 }
6695         }
6696 }
6697
6698 /*-----------------------------------------------------------------*/
6699 /* shiftLeft_Left2ResultLit - shift left by known count            */
6700 /*-----------------------------------------------------------------*/
6701
6702 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6703 {
6704         int size, same, offr, i;
6705
6706         size = AOP_SIZE(left);
6707         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6708         
6709         same = pic14_sameRegs (AOP(left), AOP(result));
6710         
6711         offr = shCount / 8;
6712         shCount = shCount & 0x07;
6713
6714         size -= offr;
6715
6716         switch (shCount)
6717         {
6718         case 0: /* takes 0 or 2N cycles (for offr==0) */
6719                 if (!same || offr) {
6720                         for (i=size-1; i >= 0; i--)
6721                                 movLeft2Result (left, i, result, offr + i);
6722                 } // if
6723                 break;
6724                 
6725         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6726                 if (same && offr) {
6727                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6728                         shiftLeft_Left2ResultLit (result, result, shCount);
6729                         return; /* prevent clearing result again */
6730                 } else {
6731                         emitCLRC;
6732                         for (i=0; i < size; i++) {
6733                                 if (same && !offr) {
6734                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6735                                 } else {
6736                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6737                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6738                                 } // if
6739                         } // for
6740                 } // if (offr)
6741                 break;
6742                 
6743         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6744                 /* works in-place/with offr as well */
6745                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6746                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6747                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6748
6749                 for (i = size - 2; i >= 0; i--)
6750                 {
6751                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6752                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6753                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6754                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6755                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6756                 } // for i
6757                 break;
6758                 
6759         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6760                 /* works in-place/with offr as well */
6761                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6762                 for (i = size-2; i >= 0; i--) {
6763                         emitpcode (POC_RRFW, popGet (AOP(left), i));
6764                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6765                 } // for i
6766                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6767                 emitpcode (POC_RRF, popGet (AOP(result), offr));
6768                 break;
6769         
6770         default:
6771                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6772                 shiftLeft_Left2ResultLit (result, result, 1);
6773                 return; /* prevent clearing result again */
6774                 break;
6775         } // switch
6776
6777         while (0 < offr--)
6778         {
6779                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6780         } // while
6781 }
6782
6783 /*-----------------------------------------------------------------*/
6784 /* shiftRight_Left2ResultLit - shift right by known count          */
6785 /*-----------------------------------------------------------------*/
6786
6787 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6788 {
6789         int size, same, offr, i;
6790
6791         size = AOP_SIZE(left);
6792         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6793         
6794         same = pic14_sameRegs (AOP(left), AOP(result));
6795         
6796         offr = shCount / 8;
6797         shCount = shCount & 0x07;
6798
6799         size -= offr;
6800
6801         if (size)
6802         {
6803                 switch (shCount)
6804                 {
6805                 case 0: /* takes 0 or 2N cycles (for offr==0) */
6806                         if (!same || offr) {
6807                                 for (i=0; i < size; i++)
6808                                         movLeft2Result (left, i + offr, result, i);
6809                         } // if
6810                         break;
6811                         
6812                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6813                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6814                         if (same && offr) {
6815                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6816                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
6817                                 return; /* prevent sign-extending result again */
6818                         } else {
6819                                 emitCLRC;
6820                                 if (sign) {
6821                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6822                                         emitSETC;
6823                                 }
6824                                 for (i = size-1; i >= 0; i--) {
6825                                         if (same && !offr) {
6826                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
6827                                         } else {
6828                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6829                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6830                                         }
6831                                 } // for i
6832                         } // if (offr)
6833                         break;
6834                         
6835                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6836                         /* works in-place/with offr as well */
6837                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6838                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6839                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
6840
6841                         for (i = 1; i < size; i++)
6842                         {
6843                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
6844                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6845                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6846                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
6847                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
6848                         } // for i
6849
6850                         if (sign)
6851                         {
6852                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
6853                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
6854                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
6855                         } // if
6856                         break;
6857                         
6858                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
6859                         /* works in-place/with offr as well */
6860                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
6861                         for (i = 0; i < size-1; i++) {
6862                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
6863                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6864                         } // for i
6865                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
6866                         if (!sign) {
6867                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
6868                         } else {
6869                                 emitSKPNC;
6870                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
6871                         }
6872                         break;
6873                 
6874                 default:
6875                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
6876                         shiftRight_Left2ResultLit (result, result, 1, sign);
6877                         return; /* prevent sign extending result again */
6878                         break;
6879                 } // switch
6880         } // if
6881
6882         addSign (result, size, sign);
6883 }
6884
6885 #if 0
6886 /*-----------------------------------------------------------------*/
6887 /* shiftL2Left2Result - shift left two bytes from left to result   */
6888 /*-----------------------------------------------------------------*/
6889 static void shiftL2Left2Result (operand *left, int offl,
6890                                                                 operand *result, int offr, int shCount)
6891 {
6892         FENTRY;
6893         
6894         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6895         
6896         if(pic14_sameRegs(AOP(result), AOP(left))) {
6897                 switch(shCount) {
6898                 case 0:
6899                         break;
6900                 case 1:
6901                 case 2:
6902                 case 3:
6903                         
6904                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6905                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6906                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6907                         
6908                         while(--shCount) {
6909                                 emitCLRC;
6910                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6911                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6912                         }
6913                         
6914                         break;
6915                 case 4:
6916                 case 5:
6917                         emitpcode(POC_MOVLW, popGetLit(0x0f));
6918                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6919                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6920                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6921                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6922                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
6923                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6924                         if(shCount >=5) {
6925                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6926                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6927                         }
6928                         break;
6929                 case 6:
6930                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6931                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6932                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6933                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6934                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6935                         emitpcode(POC_ANDLW,popGetLit(0xc0));
6936                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6937                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
6938                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6939                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6940                         break;
6941                 case 7:
6942                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6943                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
6944                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6945                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
6946                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6947                 }
6948                 
6949         } else {
6950                 switch(shCount) {
6951                 case 0:
6952                         break;
6953                 case 1:
6954                 case 2:
6955                 case 3:
6956                 /* note, use a mov/add for the shift since the mov has a
6957                         chance of getting optimized out */
6958                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6959                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6960                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6961                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6962                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6963                         
6964                         while(--shCount) {
6965                                 emitCLRC;
6966                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6967                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6968                         }
6969                         break;
6970                         
6971                 case 4:
6972                 case 5:
6973                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6974                         emitpcode(POC_ANDLW, popGetLit(0xF0));
6975                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6976                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6977                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6978                         emitpcode(POC_ANDLW, popGetLit(0xF0));
6979                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
6980                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6981                         
6982                         
6983                         if(shCount == 5) {
6984                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6985                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6986                         }
6987                         break;
6988                 case 6:
6989                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6990                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6991                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
6992                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6993                         
6994                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6995                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6996                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6997                         emitpcode(POC_ANDLW,popGetLit(0xc0));
6998                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6999                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7000                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7001                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7002                         break;
7003                 case 7:
7004                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7005                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7006                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7007                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7008                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7009                 }
7010         }
7011         
7012 }
7013
7014 /*-----------------------------------------------------------------*/
7015 /* shiftR2Left2Result - shift right two bytes from left to result  */
7016 /*-----------------------------------------------------------------*/
7017 static void shiftR2Left2Result (operand *left, int offl,
7018                                                                 operand *result, int offr,
7019                                                                 int shCount, int sign)
7020 {
7021         int same=0;
7022         
7023         FENTRY;
7024         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7025         same = pic14_sameRegs(AOP(result), AOP(left));
7026         
7027         if(same && ((offl + MSB16) == offr)){
7028                 same=1;
7029                 /* don't crash result[offr] */
7030                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7031                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7032         }
7033         /* else {
7034         movLeft2Result(left,offl, result, offr);
7035         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7036         }
7037         */
7038         /* a:x >> shCount (x = lsb(result))*/
7039         /*
7040         if(sign)
7041         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7042         else {
7043         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7044         */
7045         switch(shCount) {
7046         case 0:
7047                 break;
7048         case 1:
7049         case 2:
7050         case 3:
7051                 if(sign)
7052                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7053                 else
7054                         emitCLRC;
7055                 
7056                 if(same) {
7057                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7058                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7059                 } else {
7060                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7061                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7062                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7063                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7064                 }
7065                 
7066                 while(--shCount) {
7067                         if(sign)
7068                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7069                         else
7070                                 emitCLRC;
7071                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7072                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7073                 }
7074                 break;
7075         case 4:
7076         case 5:
7077                 if(same) {
7078                         
7079                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7080                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7081                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7082                         
7083                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7084                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7085                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7086                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7087                 } else {
7088                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7089                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7090                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7091                         
7092                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7093                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7094                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7095                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7096                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7097                 }
7098                 
7099                 if(shCount >=5) {
7100                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7101                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7102                 }
7103                 
7104                 if(sign) {
7105                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7106                         emitpcode(POC_BTFSC, 
7107                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7108                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7109                 }
7110                 
7111                 break;
7112                 
7113         case 6:
7114                 if(same) {
7115                         
7116                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7117                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7118                         
7119                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7120                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7121                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7122                         emitpcode(POC_ANDLW,popGetLit(0x03));
7123                         if(sign) {
7124                                 emitpcode(POC_BTFSC, 
7125                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7126                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7127                         }
7128                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7129                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7130                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7131                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7132                 } else {
7133                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7134                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7135                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7136                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7137                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7138                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7139                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7140                         emitpcode(POC_ANDLW,popGetLit(0x03));
7141                         if(sign) {
7142                                 emitpcode(POC_BTFSC, 
7143                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7144                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7145                         }
7146                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7147                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7148                         
7149                         
7150                 }
7151                 
7152                 break;
7153         case 7:
7154                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7155                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7156                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7157                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7158                 if(sign) {
7159                         emitSKPNC;
7160                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7161                 } else 
7162                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7163   }
7164 }
7165
7166 /*-----------------------------------------------------------------*/
7167 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7168 /*-----------------------------------------------------------------*/
7169 static void shiftLLeftOrResult (operand *left, int offl,
7170                                                                 operand *result, int offr, int shCount)
7171 {
7172         FENTRY;
7173         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7174         
7175         /* shift left accumulator */
7176         AccLsh(left,offl,shCount);
7177         /* or with result */
7178         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7179         assert ( !"broken (modifies left, fails for left==result))" );
7180 }
7181
7182 /*-----------------------------------------------------------------*/
7183 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7184 /*-----------------------------------------------------------------*/
7185 static void shiftRLeftOrResult (operand *left, int offl,
7186                                                                 operand *result, int offr, int shCount)
7187 {
7188         FENTRY;
7189         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7190         
7191         /* shift right accumulator */
7192         AccRsh(left,offl,shCount);
7193         /* or with result */
7194         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7195         assert ( !"broken (modifies left, fails for left==result))" );
7196 }
7197
7198 /*-----------------------------------------------------------------*/
7199 /* genlshOne - left shift a one byte quantity by known count       */
7200 /*-----------------------------------------------------------------*/
7201 static void genlshOne (operand *result, operand *left, int shCount)
7202 {       
7203         FENTRY;
7204         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7205         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7206 }
7207
7208 /*-----------------------------------------------------------------*/
7209 /* genlshTwo - left shift two bytes by known amount != 0           */
7210 /*-----------------------------------------------------------------*/
7211 static void genlshTwo (operand *result,operand *left, int shCount)
7212 {
7213         int size;
7214         
7215         FENTRY;
7216         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7217         size = pic14_getDataSize(result);
7218         
7219         /* if shCount >= 8 */
7220         if (shCount >= 8) {
7221                 shCount -= 8 ;
7222                 
7223                 if (size > 1){
7224                         if (shCount)
7225                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7226                         else 
7227                                 movLeft2Result(left, LSB, result, MSB16);
7228                 }
7229                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7230         }
7231         
7232         /*  1 <= shCount <= 7 */
7233         else {  
7234                 if(size == 1)
7235                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7236                 else 
7237                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7238         }
7239 }
7240
7241 /*-----------------------------------------------------------------*/
7242 /* shiftLLong - shift left one long from left to result            */
7243 /* offl = LSB or MSB16                                             */
7244 /*-----------------------------------------------------------------*/
7245 static void shiftLLong (operand *left, operand *result, int offr )
7246 {
7247         char *l;
7248         int size = AOP_SIZE(result);
7249         
7250         FENTRY;
7251         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7252         if(size >= LSB+offr){
7253                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7254                 MOVA(l);
7255                 pic14_emitcode("add","a,acc");
7256                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7257                         size >= MSB16+offr && offr != LSB )
7258                         pic14_emitcode("xch","a,%s",
7259                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7260                 else      
7261                         aopPut(AOP(result),"a",LSB+offr);
7262         }
7263         
7264         if(size >= MSB16+offr){
7265                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7266                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7267                         MOVA(l);
7268                 }
7269                 pic14_emitcode("rlc","a");
7270                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7271                         size >= MSB24+offr && offr != LSB)
7272                         pic14_emitcode("xch","a,%s",
7273                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7274                 else      
7275                         aopPut(AOP(result),"a",MSB16+offr);
7276         }
7277         
7278         if(size >= MSB24+offr){
7279                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7280                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7281                         MOVA(l);
7282                 }
7283                 pic14_emitcode("rlc","a");
7284                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7285                         size >= MSB32+offr && offr != LSB )
7286                         pic14_emitcode("xch","a,%s",
7287                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7288                 else      
7289                         aopPut(AOP(result),"a",MSB24+offr);
7290         }
7291         
7292         if(size > MSB32+offr){
7293                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7294                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7295                         MOVA(l);  
7296                 }
7297                 pic14_emitcode("rlc","a");
7298                 aopPut(AOP(result),"a",MSB32+offr);
7299         }
7300         if(offr != LSB)
7301                 aopPut(AOP(result),zero,LSB);       
7302 }
7303
7304 /*-----------------------------------------------------------------*/
7305 /* genlshFour - shift four byte by a known amount != 0             */
7306 /*-----------------------------------------------------------------*/
7307 static void genlshFour (operand *result, operand *left, int shCount)
7308 {
7309         int size;
7310         
7311         FENTRY;
7312         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7313         size = AOP_SIZE(result);
7314         
7315         /* if shifting more that 3 bytes */
7316         if (shCount >= 24 ) {
7317                 shCount -= 24;
7318                 if (shCount)
7319                 /* lowest order of left goes to the highest
7320                 order of the destination */
7321                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7322                 else
7323                         movLeft2Result(left, LSB, result, MSB32);
7324                 aopPut(AOP(result),zero,LSB);
7325                 aopPut(AOP(result),zero,MSB16);
7326                 aopPut(AOP(result),zero,MSB32);
7327                 return;
7328         }
7329         
7330         /* more than two bytes */
7331         else if ( shCount >= 16 ) {
7332                 /* lower order two bytes goes to higher order two bytes */
7333                 shCount -= 16;
7334                 /* if some more remaining */
7335                 if (shCount)
7336                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7337                 else {
7338                         movLeft2Result(left, MSB16, result, MSB32);
7339                         movLeft2Result(left, LSB, result, MSB24);
7340                 }
7341                 aopPut(AOP(result),zero,MSB16);
7342                 aopPut(AOP(result),zero,LSB);
7343                 return;
7344         }    
7345         
7346         /* if more than 1 byte */
7347         else if ( shCount >= 8 ) {
7348                 /* lower order three bytes goes to higher order  three bytes */
7349                 shCount -= 8;
7350                 if(size == 2){
7351                         if(shCount)
7352                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7353                         else
7354                                 movLeft2Result(left, LSB, result, MSB16);
7355                 }
7356                 else{   /* size = 4 */
7357                         if(shCount == 0){
7358                                 movLeft2Result(left, MSB24, result, MSB32);
7359                                 movLeft2Result(left, MSB16, result, MSB24);
7360                                 movLeft2Result(left, LSB, result, MSB16);
7361                                 aopPut(AOP(result),zero,LSB);
7362                         }
7363                         else if(shCount == 1)
7364                                 shiftLLong(left, result, MSB16);
7365                         else{
7366                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7367                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7368                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7369                                 aopPut(AOP(result),zero,LSB);
7370                         }
7371                 }
7372         }
7373         
7374         /* 1 <= shCount <= 7 */
7375         else if(shCount <= 2){
7376                 shiftLLong(left, result, LSB);
7377                 if(shCount == 2)
7378                         shiftLLong(result, result, LSB);
7379         }
7380         /* 3 <= shCount <= 7, optimize */
7381         else{
7382                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7383                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7384                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7385         }
7386 }
7387 #endif
7388
7389 #if 0
7390 /*-----------------------------------------------------------------*/
7391 /* genLeftShiftLiteral - left shifting by known count              */
7392 /*-----------------------------------------------------------------*/
7393 static void genLeftShiftLiteral (operand *left,
7394                                                                  operand *right,
7395                                                                  operand *result,
7396                                                                  iCode *ic)
7397 {    
7398         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7399         //int size;
7400         
7401         FENTRY;
7402         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7403         freeAsmop(right,NULL,ic,TRUE);
7404         
7405         aopOp(left,ic,FALSE);
7406         aopOp(result,ic,FALSE);
7407
7408         size = getSize(operandType(result));
7409         
7410 #if VIEW_SIZE
7411         pic14_emitcode("; shift left ","result %d, left %d",size,
7412                 AOP_SIZE(left));
7413 #endif
7414         
7415         /* I suppose that the left size >= result size */
7416         if(shCount == 0){
7417                 while(size--){
7418                         movLeft2Result(left, size, result, size);
7419                 }
7420         }
7421         
7422         else if(shCount >= (size * 8))
7423                 while(size--)
7424                         aopPut(AOP(result),zero,size);
7425                 else{
7426                         switch (size) {
7427                         case 1:
7428                                 genlshOne (result,left,shCount);
7429                                 break;
7430                                 
7431                         case 2:
7432                         case 3:
7433                                 genlshTwo (result,left,shCount);
7434                                 break;
7435                                 
7436                         case 4:
7437                                 genlshFour (result,left,shCount);
7438                                 break;
7439                         }
7440                 }
7441                 freeAsmop(left,NULL,ic,TRUE);
7442                 freeAsmop(result,NULL,ic,TRUE);
7443 }
7444 #endif
7445
7446 /*-----------------------------------------------------------------*
7447 * genMultiAsm - repeat assembly instruction for size of register.
7448 * if endian == 1, then the high byte (i.e base address + size of 
7449 * register) is used first else the low byte is used first;
7450 *-----------------------------------------------------------------*/
7451 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7452 {
7453         
7454         int offset = 0;
7455         
7456         FENTRY;
7457         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7458         
7459         if(!reg)
7460                 return;
7461         
7462         if(!endian) {
7463                 endian = 1;
7464         } else {
7465                 endian = -1;
7466                 offset = size-1;
7467         }
7468         
7469         while(size--) {
7470                 emitpcode(poc,    popGet(AOP(reg),offset));
7471                 offset += endian;
7472         }
7473         
7474 }
7475 /*-----------------------------------------------------------------*/
7476 /* genLeftShift - generates code for left shifting                 */
7477 /*-----------------------------------------------------------------*/
7478 static void genLeftShift (iCode *ic)
7479 {
7480         operand *left,*right, *result;
7481         int size, offset;
7482         unsigned long lit = 0L;
7483         char *l;
7484         symbol *tlbl , *tlbl1;
7485         pCodeOp *pctemp;
7486         
7487         FENTRY;
7488         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7489         
7490         right = IC_RIGHT(ic);
7491         left  = IC_LEFT(ic);
7492         result = IC_RESULT(ic);
7493         
7494         aopOp(right,ic,FALSE);
7495         aopOp(left,ic,FALSE);
7496         aopOp(result,ic,FALSE);
7497         
7498         
7499         /* if the shift count is known then do it 
7500         as efficiently as possible */
7501         if (AOP_TYPE(right) == AOP_LIT) {
7502                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7503                 return ;
7504         }
7505         
7506         /* shift count is unknown then we have to form 
7507         a loop get the loop count in B : Note: we take
7508         only the lower order byte since shifting
7509         more that 32 bits make no sense anyway, ( the
7510         largest size of an object can be only 32 bits ) */  
7511         
7512         
7513         /* now move the left to the result if they are not the
7514         same */
7515         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7516                 AOP_SIZE(result) > 1) {
7517                 
7518                 size = AOP_SIZE(result);
7519                 offset=0;
7520                 while (size--) {
7521                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7522                         if (*l == '@' && (IS_AOP_PREG(result))) {
7523                                 
7524                                 pic14_emitcode("mov","a,%s",l);
7525                                 aopPut(AOP(result),"a",offset);
7526                         } else {
7527                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7528                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7529                                 //aopPut(AOP(result),l,offset);
7530                         }
7531                         offset++;
7532                 }
7533         }
7534         
7535         if(AOP_TYPE(left) == AOP_LIT)
7536                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7537
7538         size = AOP_SIZE(result);
7539         
7540         /* if it is only one byte then */
7541         if (size == 1) {
7542                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7543                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7544                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7545                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7546                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7547                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7548                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7549                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7550                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7551                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7552                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7553                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7554                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7555                 } else {
7556                         
7557                         tlbl = newiTempLabel(NULL);
7558                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7559                                 if (AOP_TYPE(left) == AOP_LIT)
7560                                         emitpcode(POC_MOVLW,  popGetLit(lit));
7561                                 else
7562                                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7563                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7564                         }
7565                         
7566                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7567                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7568                         emitpLabel(tlbl->key);
7569                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7570                         emitpcode(POC_ADDLW,  popGetLit(1));
7571                         emitSKPC;
7572                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7573                 }
7574                 goto release ;
7575         }
7576         
7577         if (pic14_sameRegs(AOP(left),AOP(result))) {
7578                 
7579                 tlbl = newiTempLabel(NULL);
7580                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7581                 genMultiAsm(POC_RRF, result, size,1);
7582                 emitpLabel(tlbl->key);
7583                 genMultiAsm(POC_RLF, result, size,0);
7584                 emitpcode(POC_ADDLW,  popGetLit(1));
7585                 emitSKPC;
7586                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7587                 goto release;
7588         }
7589         
7590         //tlbl = newiTempLabel(NULL);
7591         //offset = 0 ;   
7592         //tlbl1 = newiTempLabel(NULL);
7593         
7594         //reAdjustPreg(AOP(result));    
7595         
7596         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7597         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7598         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7599         //MOVA(l);
7600         //pic14_emitcode("add","a,acc");         
7601         //aopPut(AOP(result),"a",offset++);
7602         //while (--size) {
7603         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7604         //  MOVA(l);
7605         //  pic14_emitcode("rlc","a");         
7606         //  aopPut(AOP(result),"a",offset++);
7607         //}
7608         //reAdjustPreg(AOP(result));
7609         
7610         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7611         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7612         
7613         
7614         tlbl = newiTempLabel(NULL);
7615         tlbl1= newiTempLabel(NULL);
7616         
7617         size = AOP_SIZE(result);
7618         offset = 1;
7619         
7620         pctemp = popGetTempReg();  /* grab a temporary working register. */
7621         
7622         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7623         
7624         /* offset should be 0, 1 or 3 */
7625         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7626         emitSKPNZ;
7627         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7628         
7629         emitpcode(POC_MOVWF, pctemp);
7630         
7631         
7632         emitpLabel(tlbl->key);
7633         
7634         emitCLRC;
7635         emitpcode(POC_RLF,  popGet(AOP(result),0));
7636         while(--size)
7637                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7638         
7639         emitpcode(POC_DECFSZ,  pctemp);
7640         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7641         emitpLabel(tlbl1->key);
7642         
7643         popReleaseTempReg(pctemp);
7644         
7645         
7646 release:
7647         freeAsmop (right,NULL,ic,TRUE);
7648         freeAsmop(left,NULL,ic,TRUE);
7649         freeAsmop(result,NULL,ic,TRUE);
7650 }
7651
7652 #if 0
7653 /*-----------------------------------------------------------------*/
7654 /* genrshOne - right shift a one byte quantity by known count      */
7655 /*-----------------------------------------------------------------*/
7656 static void genrshOne (operand *result, operand *left,
7657                                            int shCount, int sign)
7658 {
7659         FENTRY;
7660         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7661         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7662 }
7663
7664 /*-----------------------------------------------------------------*/
7665 /* genrshTwo - right shift two bytes by known amount != 0          */
7666 /*-----------------------------------------------------------------*/
7667 static void genrshTwo (operand *result,operand *left,
7668                                            int shCount, int sign)
7669 {
7670         FENTRY;
7671         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7672         /* if shCount >= 8 */
7673         if (shCount >= 8) {
7674                 shCount -= 8 ;
7675                 if (shCount)
7676                         shiftR1Left2Result(left, MSB16, result, LSB,
7677                         shCount, sign);
7678                 else
7679                         movLeft2Result(left, MSB16, result, LSB);
7680                 
7681                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7682                 
7683                 if(sign) {
7684                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7685                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7686                 }
7687         }
7688         
7689         /*  1 <= shCount <= 7 */
7690         else
7691                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7692 }
7693
7694 /*-----------------------------------------------------------------*/
7695 /* shiftRLong - shift right one long from left to result           */
7696 /* offl = LSB or MSB16                                             */
7697 /*-----------------------------------------------------------------*/
7698 static void shiftRLong (operand *left, int offl,
7699                                                 operand *result, int sign)
7700 {
7701         int size, same;
7702         
7703         FENTRY;
7704         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7705         
7706         size = AOP_SIZE(left);
7707         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7708         
7709         if (sign)
7710                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7711         else
7712                 emitCLRC;
7713
7714         assert (offl >= 0 && offl < size);
7715
7716         same = pic14_sameRegs (AOP(left), AOP(result));
7717
7718         /* perform the shift */
7719         while (size--)
7720         {
7721                 if (same && !offl) {
7722                         emitpcode (POC_RRF, popGet (AOP(result), size));
7723                 } else {
7724                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7725                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7726                 }
7727         } // while
7728
7729         addSign (result, AOP_SIZE(left) - offl, sign);
7730 }
7731
7732 /*-----------------------------------------------------------------*/
7733 /* genrshFour - shift four byte by a known amount != 0             */
7734 /*-----------------------------------------------------------------*/
7735 static void genrshFour (operand *result, operand *left,
7736                                                 int shCount, int sign)
7737 {
7738         FENTRY;
7739         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7740         /* if shifting more that 3 bytes */
7741         if(shCount >= 24 ) {
7742                 shCount -= 24;
7743                 if(shCount)
7744                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7745                 else
7746                         movLeft2Result(left, MSB32, result, LSB);
7747                 
7748                 addSign(result, MSB16, sign);
7749         }
7750         else if(shCount >= 16){
7751                 shCount -= 16;
7752                 if(shCount)
7753                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7754                 else{
7755                         movLeft2Result(left, MSB24, result, LSB);
7756                         movLeft2Result(left, MSB32, result, MSB16);
7757                 }
7758                 addSign(result, MSB24, sign);
7759         }
7760         else if(shCount >= 8){
7761                 shCount -= 8;
7762                 if(shCount == 1)
7763                         shiftRLong(left, MSB16, result, sign);
7764                 else if(shCount == 0){
7765                         movLeft2Result(left, MSB16, result, LSB);
7766                         movLeft2Result(left, MSB24, result, MSB16);
7767                         movLeft2Result(left, MSB32, result, MSB24);
7768                         addSign(result, MSB32, sign);
7769                 }
7770                 else{
7771                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7772                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7773                         /* the last shift is signed */
7774                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7775                         addSign(result, MSB32, sign);
7776                 }
7777         }
7778         else{   /* 1 <= shCount <= 7 */
7779                 if(shCount <= 2){
7780                         shiftRLong(left, LSB, result, sign);
7781                         if(shCount == 2)
7782                                 shiftRLong(result, LSB, result, sign);
7783                 }
7784                 else{
7785                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7786                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7787                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7788                 }
7789         }
7790 }
7791
7792 /*-----------------------------------------------------------------*/
7793 /* genRightShiftLiteral - right shifting by known count            */
7794 /*-----------------------------------------------------------------*/
7795 static void genRightShiftLiteral (operand *left,
7796                                                                   operand *right,
7797                                                                   operand *result,
7798                                                                   iCode *ic,
7799                                                                   int sign)
7800 {    
7801         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7802         int lsize,res_size;
7803         
7804         FENTRY;
7805         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7806         freeAsmop(right,NULL,ic,TRUE);
7807         
7808         aopOp(left,ic,FALSE);
7809         aopOp(result,ic,FALSE);
7810         
7811 #if VIEW_SIZE
7812         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7813                 AOP_SIZE(left));
7814 #endif
7815         
7816         lsize = pic14_getDataSize(left);
7817         res_size = pic14_getDataSize(result);
7818         /* test the LEFT size !!! */
7819         
7820         /* I suppose that the left size >= result size */
7821         if(shCount == 0){
7822                 while(res_size--)
7823                         movLeft2Result(left, res_size, result, res_size);
7824         }
7825         
7826         else if(shCount >= (lsize * 8)){
7827                 
7828                 if(res_size == 1) {
7829                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7830                         if(sign) {
7831                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7832                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
7833                         }
7834                 } else {
7835                         
7836                         if(sign) {
7837                                 emitpcode(POC_MOVLW, popGetLit(0));
7838                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7839                                 emitpcode(POC_MOVLW, popGetLit(0xff));
7840                                 while(res_size--)
7841                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7842                                 
7843                         } else {
7844                                 
7845                                 while(res_size--)
7846                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7847                         }
7848                 }
7849         } else {
7850                 
7851                 switch (res_size) {
7852                 case 1:
7853                         genrshOne (result,left,shCount,sign);
7854                         break;
7855                         
7856                 case 2:
7857                         genrshTwo (result,left,shCount,sign);
7858                         break;
7859                         
7860                 case 4:
7861                         genrshFour (result,left,shCount,sign);
7862                         break;
7863                 default :
7864                         break;
7865                 }
7866                 
7867         }
7868
7869         freeAsmop(left,NULL,ic,TRUE);
7870         freeAsmop(result,NULL,ic,TRUE);
7871 }
7872 #endif
7873
7874 /*-----------------------------------------------------------------*/
7875 /* genSignedRightShift - right shift of signed number              */
7876 /*-----------------------------------------------------------------*/
7877 static void genSignedRightShift (iCode *ic)
7878 {
7879         operand *right, *left, *result;
7880         int size, offset;
7881         //  char *l;
7882         symbol *tlbl, *tlbl1 ;
7883         pCodeOp *pctemp;
7884         
7885         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7886         
7887         /* we do it the hard way put the shift count in b
7888         and loop thru preserving the sign */
7889         FENTRY;
7890         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7891         
7892         right = IC_RIGHT(ic);
7893         left  = IC_LEFT(ic);
7894         result = IC_RESULT(ic);
7895         
7896         aopOp(right,ic,FALSE);  
7897         aopOp(left,ic,FALSE);
7898         aopOp(result,ic,FALSE);
7899         
7900         
7901         if ( AOP_TYPE(right) == AOP_LIT) {
7902                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
7903                 //genRightShiftLiteral (left,right,result,ic,1);
7904                 return ;
7905         }
7906         /* shift count is unknown then we have to form 
7907         a loop get the loop count in B : Note: we take
7908         only the lower order byte since shifting
7909         more that 32 bits make no sense anyway, ( the
7910         largest size of an object can be only 32 bits ) */  
7911         
7912         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7913         //pic14_emitcode("inc","b");
7914         //freeAsmop (right,NULL,ic,TRUE);
7915         //aopOp(left,ic,FALSE);
7916         //aopOp(result,ic,FALSE);
7917         
7918         /* now move the left to the result if they are not the
7919         same */
7920         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7921                 AOP_SIZE(result) > 1) {
7922                 
7923                 size = AOP_SIZE(result);
7924                 offset=0;
7925                 while (size--) { 
7926                         /*
7927                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7928                         if (*l == '@' && IS_AOP_PREG(result)) {
7929                                 pic14_emitcode("mov","a,%s",l);
7930                                 aopPut(AOP(result),"a",offset);
7931                         } else
7932                         aopPut(AOP(result),l,offset);
7933                         */
7934                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7935                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7936                         
7937                         offset++;
7938                 }
7939         }
7940         
7941         /* mov the highest order bit to OVR */    
7942         tlbl = newiTempLabel(NULL);
7943         tlbl1= newiTempLabel(NULL);
7944         
7945         size = AOP_SIZE(result);
7946         offset = size - 1;
7947         
7948         pctemp = popGetTempReg();  /* grab a temporary working register. */
7949         
7950         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7951         
7952         /* offset should be 0, 1 or 3 */
7953         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7954         emitSKPNZ;
7955         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7956         
7957         emitpcode(POC_MOVWF, pctemp);
7958         
7959         
7960         emitpLabel(tlbl->key);
7961         
7962         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7963         emitpcode(POC_RRF,   popGet(AOP(result),offset));
7964         
7965         while(--size) {
7966                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7967         }
7968         
7969         emitpcode(POC_DECFSZ,  pctemp);
7970         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7971         emitpLabel(tlbl1->key);
7972         
7973         popReleaseTempReg(pctemp);
7974 #if 0
7975         size = AOP_SIZE(result);
7976         offset = size - 1;
7977         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7978         pic14_emitcode("rlc","a");
7979         pic14_emitcode("mov","ov,c");
7980         /* if it is only one byte then */
7981         if (size == 1) {
7982                 l = aopGet(AOP(left),0,FALSE,FALSE);
7983                 MOVA(l);
7984                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7985                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7986                 pic14_emitcode("mov","c,ov");
7987                 pic14_emitcode("rrc","a");
7988                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7989                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7990                 aopPut(AOP(result),"a",0);
7991                 goto release ;
7992         }
7993         
7994         reAdjustPreg(AOP(result));
7995         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7996         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7997         pic14_emitcode("mov","c,ov");
7998         while (size--) {
7999                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8000                 MOVA(l);
8001                 pic14_emitcode("rrc","a");         
8002                 aopPut(AOP(result),"a",offset--);
8003         }
8004         reAdjustPreg(AOP(result));
8005         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8006         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8007         
8008 release:
8009 #endif
8010         
8011         freeAsmop(left,NULL,ic,TRUE);
8012         freeAsmop(result,NULL,ic,TRUE);
8013         freeAsmop(right,NULL,ic,TRUE);
8014 }
8015
8016 /*-----------------------------------------------------------------*/
8017 /* genRightShift - generate code for right shifting                */
8018 /*-----------------------------------------------------------------*/
8019 static void genRightShift (iCode *ic)
8020 {
8021         operand *right, *left, *result;
8022         sym_link *retype ;
8023         int size, offset;
8024         char *l;
8025         symbol *tlbl, *tlbl1 ;
8026         
8027         FENTRY;
8028         /* if signed then we do it the hard way preserve the
8029         sign bit moving it inwards */
8030         retype = getSpec(operandType(IC_RESULT(ic)));
8031         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8032         
8033         if (!SPEC_USIGN(retype)) {
8034                 genSignedRightShift (ic);
8035                 return ;
8036         }
8037         
8038         /* signed & unsigned types are treated the same : i.e. the
8039         signed is NOT propagated inwards : quoting from the
8040         ANSI - standard : "for E1 >> E2, is equivalent to division
8041         by 2**E2 if unsigned or if it has a non-negative value,
8042         otherwise the result is implementation defined ", MY definition
8043         is that the sign does not get propagated */
8044         
8045         right = IC_RIGHT(ic);
8046         left  = IC_LEFT(ic);
8047         result = IC_RESULT(ic);
8048         
8049         aopOp(right,ic,FALSE);
8050         aopOp(left,ic,FALSE);
8051         aopOp(result,ic,FALSE);
8052         
8053         /* if the shift count is known then do it 
8054         as efficiently as possible */
8055         if (AOP_TYPE(right) == AOP_LIT) {
8056                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
8057                 //genRightShiftLiteral (left,right,result,ic, 0);
8058                 return ;
8059         }
8060         
8061         /* shift count is unknown then we have to form 
8062         a loop get the loop count in B : Note: we take
8063         only the lower order byte since shifting
8064         more that 32 bits make no sense anyway, ( the
8065         largest size of an object can be only 32 bits ) */  
8066         
8067         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8068         pic14_emitcode("inc","b");
8069         
8070         /* now move the left to the result if they are not the
8071         same */
8072         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8073                 AOP_SIZE(result) > 1) {
8074                 
8075                 size = AOP_SIZE(result);
8076                 offset=0;
8077                 while (size--) {
8078                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8079                         if (*l == '@' && IS_AOP_PREG(result)) {
8080                                 
8081                                 pic14_emitcode("mov","a,%s",l);
8082                                 aopPut(AOP(result),"a",offset);
8083                         } else
8084                                 aopPut(AOP(result),l,offset);
8085                         offset++;
8086                 }
8087         }
8088         
8089         tlbl = newiTempLabel(NULL);
8090         tlbl1= newiTempLabel(NULL);
8091         size = AOP_SIZE(result);
8092         offset = size - 1;
8093         
8094         /* if it is only one byte then */
8095         if (size == 1) {
8096                 
8097                 tlbl = newiTempLabel(NULL);
8098                 if (!pic14_sameRegs(AOP(left),AOP(result))) {
8099                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
8100                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
8101                 }
8102                 
8103                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
8104                 emitpcode(POC_RLF,    popGet(AOP(result),0));
8105                 emitpLabel(tlbl->key);
8106                 emitpcode(POC_RRF,    popGet(AOP(result),0));
8107                 emitpcode(POC_ADDLW,  popGetLit(1));
8108                 emitSKPC;
8109                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8110                 
8111                 goto release ;
8112         }
8113         
8114         reAdjustPreg(AOP(result));
8115         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8116         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8117         CLRC;
8118         while (size--) {
8119                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8120                 MOVA(l);
8121                 pic14_emitcode("rrc","a");         
8122                 aopPut(AOP(result),"a",offset--);
8123         }
8124         reAdjustPreg(AOP(result));
8125         
8126         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8127         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8128         
8129 release:
8130         freeAsmop(left,NULL,ic,TRUE);
8131         freeAsmop (right,NULL,ic,TRUE);
8132         freeAsmop(result,NULL,ic,TRUE);
8133 }
8134
8135 /*-----------------------------------------------------------------*/
8136 /* genUnpackBits - generates code for unpacking bits               */
8137 /*-----------------------------------------------------------------*/
8138 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
8139 {    
8140         int shCnt;
8141         int offset = 0;       /* result byte offset */
8142         int rsize;            /* result size */
8143         int rlen = 0;         /* remaining bitfield length */
8144         sym_link *etype;      /* bitfield type information */
8145         int blen;             /* bitfield length */
8146         int bstr;             /* bitfield starting bit within byte */
8147
8148         FENTRY;
8149         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8150         etype = getSpec(operandType(result));
8151         rsize = getSize (operandType (result));
8152         blen = SPEC_BLEN (etype);
8153         bstr = SPEC_BSTR (etype);
8154         
8155         /* single bit field case */
8156         if (blen == 1) {
8157                 if (ifx) { /* that is for an if statement */
8158                         pCodeOp *pcop;
8159                         resolvedIfx rIfx;
8160                         resolveIfx(&rIfx,ifx);
8161                         if (ptype == -1) /* direct */
8162                                 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8163                         else
8164                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8165                         emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8166                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8167                         ifx->generated=1;
8168                 } else {
8169                         pCodeOp *pcop;
8170                         if (ptype == -1) /* direct */
8171                                 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8172                         else
8173                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8174                         emitpcode(POC_BTFSC,pcop);
8175                         emitpcode(POC_BSF,newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0));
8176
8177                         if (ptype == -1) /* direct */
8178                                 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8179                         else
8180                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8181                         emitpcode(POC_BTFSS,pcop);
8182                         emitpcode(POC_BCF,newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0));
8183                 }
8184                 return;
8185         }
8186
8187         /* read the first byte  */
8188         switch (ptype) {
8189                 
8190         case POINTER:
8191         case IPOINTER:
8192 //              pic14_emitcode("mov","a,@%s",rname);
8193                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8194                 break;
8195                 
8196         case PPOINTER:
8197                 pic14_emitcode("movx","a,@%s",rname);
8198                 break;
8199                 
8200         case FPOINTER:
8201                 pic14_emitcode("movx","a,@dptr");
8202                 break;
8203                 
8204         case CPOINTER:
8205                 pic14_emitcode("clr","a");
8206                 pic14_emitcode("movc","a","@a+dptr");
8207                 break;
8208                 
8209         case GPOINTER:
8210                 pic14_emitcode("lcall","__gptrget");
8211                 break;
8212         }
8213
8214         /* if we have bitdisplacement then it fits   */
8215         /* into this byte completely or if length is */
8216         /* less than a byte                          */
8217         if ((shCnt = SPEC_BSTR(etype)) || blen <= 8)  {
8218                 
8219                 /* shift right acc */
8220                 AccRsh(left,0,shCnt);
8221                 
8222                 pic14_emitcode("anl","a,#0x%02x",
8223                         ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8224                 aopPut(AOP(result),"a",offset);
8225                 return ;
8226         }
8227         
8228         /* bit field did not fit in a byte  */
8229         rlen = SPEC_BLEN(etype) - 8;
8230         aopPut(AOP(result),"a",offset++);
8231         
8232         while (1)  {
8233                 
8234                 switch (ptype) {
8235                 case POINTER:
8236                 case IPOINTER:
8237                         pic14_emitcode("inc","%s",rname);
8238                         pic14_emitcode("mov","a,@%s",rname);
8239                         break;
8240                         
8241                 case PPOINTER:
8242                         pic14_emitcode("inc","%s",rname);
8243                         pic14_emitcode("movx","a,@%s",rname);
8244                         break;
8245                         
8246                 case FPOINTER:
8247                         pic14_emitcode("inc","dptr");
8248                         pic14_emitcode("movx","a,@dptr");
8249                         break;
8250                         
8251                 case CPOINTER:
8252                         pic14_emitcode("clr","a");
8253                         pic14_emitcode("inc","dptr");
8254                         pic14_emitcode("movc","a","@a+dptr");
8255                         break;
8256                         
8257                 case GPOINTER:
8258                         pic14_emitcode("inc","dptr");
8259                         pic14_emitcode("lcall","__gptrget");
8260                         break;
8261                 }
8262                 
8263                 rlen -= 8;            
8264                 /* if we are done */
8265                 if ( rlen <= 0 )
8266                         break ;
8267                 
8268                 aopPut(AOP(result),"a",offset++);
8269                 
8270         }
8271         
8272         if (rlen) {
8273                 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8274                 aopPut(AOP(result),"a",offset);        
8275         }
8276         
8277         return ;
8278 }
8279
8280 #if 1
8281 /*-----------------------------------------------------------------*/
8282 /* genDataPointerGet - generates code when ptr offset is known     */
8283 /*-----------------------------------------------------------------*/
8284 static void genDataPointerGet (operand *left, 
8285         operand *result, 
8286         iCode *ic)
8287 {
8288         int size , offset = 0;
8289                 
8290         FENTRY;
8291         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8292         
8293         
8294         /* optimization - most of the time, left and result are the same
8295         * address, but different types. for the pic code, we could omit
8296         * the following
8297         */
8298         aopOp(result,ic,TRUE);
8299         
8300         if (pic14_sameRegs (AOP(left), AOP(result)))
8301                 return;
8302         
8303         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8304         
8305         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8306         
8307         size = AOP_SIZE(result);
8308         if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
8309         
8310         while (size--) {
8311                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8312                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8313                 offset++;
8314         }
8315         
8316         freeAsmop(left,NULL,ic,TRUE);
8317         freeAsmop(result,NULL,ic,TRUE);
8318 }
8319 #endif
8320 /*-----------------------------------------------------------------*/
8321 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8322 /*-----------------------------------------------------------------*/
8323 static void genNearPointerGet (operand *left, 
8324                                                            operand *result, 
8325                                                            iCode *ic)
8326 {
8327         asmop *aop = NULL;
8328         sym_link *ltype = operandType(left);
8329         sym_link *rtype = operandType(result);
8330         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8331         int direct = 0;
8332
8333         FENTRY;
8334         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8335         
8336         
8337         aopOp(left,ic,FALSE);
8338         
8339         /* if left is rematerialisable and
8340         result is not bit variable type and
8341         the left is pointer to data space i.e
8342         lower 128 bytes of space */
8343         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8344                 !IS_BITVAR(retype)         &&
8345                 DCL_TYPE(ltype) == POINTER) {
8346                 genDataPointerGet (left,result,ic);
8347                 return ;
8348         }
8349         
8350         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8351         aopOp (result,ic,FALSE);
8352         
8353         /* Check if can access directly instead of via a pointer */
8354         if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
8355                 direct = 1;
8356         }
8357
8358         /* If the pointer value is not in a the FSR then need to put it in */
8359         if (!AOP_INPREG(AOP(left)) && !direct) {
8360                 /* otherwise get a free pointer register */
8361                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8362                 if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */ 
8363                         emitpcode(POC_MOVLW, popGet(AOP(left),0));
8364                 else
8365                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
8366                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8367         }
8368         
8369         
8370 //      sym_link *etype;
8371         /* if bitfield then unpack the bits */
8372         if (IS_BITFIELD(retype)) 
8373                 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8374         else {
8375                 /* we have can just get the values */
8376                 int size = AOP_SIZE(result);
8377                 int offset = 0 ;  
8378                 
8379                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8380                 
8381                 while(size--) {
8382                         if (direct)
8383                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8384                         else
8385                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8386                         if (AOP_TYPE(result) == AOP_LIT) {
8387                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8388                         } else {
8389                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8390                         }
8391                         if (size && !direct)
8392                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8393                         offset++;
8394                 }
8395         }
8396         
8397         /* now some housekeeping stuff */
8398         if (aop) {
8399                 /* we had to allocate for this iCode */
8400                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8401                 freeAsmop(NULL,aop,ic,TRUE);
8402         } else { 
8403                 /* we did not allocate which means left
8404                 already in a pointer register, then
8405                 if size > 0 && this could be used again
8406                 we have to point it back to where it 
8407                 belongs */
8408                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8409                 if (AOP_SIZE(result) > 1 &&
8410                         !OP_SYMBOL(left)->remat &&
8411                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8412                         ic->depth )) {
8413                         int size = AOP_SIZE(result) - 1;
8414                         while (size--)
8415                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8416                 }
8417         }
8418         
8419         /* done */
8420         freeAsmop(left,NULL,ic,TRUE);
8421         freeAsmop(result,NULL,ic,TRUE);
8422
8423 }
8424
8425 /*-----------------------------------------------------------------*/
8426 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8427 /*-----------------------------------------------------------------*/
8428 static void genPagedPointerGet (operand *left, 
8429                                                                 operand *result, 
8430                                                                 iCode *ic)
8431 {
8432         asmop *aop = NULL;
8433         regs *preg = NULL ;
8434         char *rname ;
8435         sym_link *rtype, *retype;    
8436         
8437         FENTRY;
8438         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8439         
8440         rtype = operandType(result);
8441         retype= getSpec(rtype);
8442         
8443         aopOp(left,ic,FALSE);
8444         
8445         /* if the value is already in a pointer register
8446         then don't need anything more */
8447         if (!AOP_INPREG(AOP(left))) {
8448                 /* otherwise get a free pointer register */
8449                 aop = newAsmop(0);
8450                 preg = getFreePtr(ic,&aop,FALSE);
8451                 pic14_emitcode("mov","%s,%s",
8452                         preg->name,
8453                         aopGet(AOP(left),0,FALSE,TRUE));
8454                 rname = preg->name ;
8455         } else
8456                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8457         
8458         freeAsmop(left,NULL,ic,TRUE);
8459         aopOp (result,ic,FALSE);
8460         
8461         /* if bitfield then unpack the bits */
8462         if (IS_BITFIELD(retype)) 
8463                 genUnpackBits (result,left,rname,PPOINTER,0);
8464         else {
8465                 /* we have can just get the values */
8466                 int size = AOP_SIZE(result);
8467                 int offset = 0 ;  
8468                 
8469                 while (size--) {
8470                         
8471                         pic14_emitcode("movx","a,@%s",rname);
8472                         aopPut(AOP(result),"a",offset);
8473                         
8474                         offset++ ;
8475                         
8476                         if (size)
8477                                 pic14_emitcode("inc","%s",rname);
8478                 }
8479         }
8480         
8481         /* now some housekeeping stuff */
8482         if (aop) {
8483                 /* we had to allocate for this iCode */
8484                 freeAsmop(NULL,aop,ic,TRUE);
8485         } else { 
8486         /* we did not allocate which means left
8487         already in a pointer register, then
8488         if size > 0 && this could be used again
8489         we have to point it back to where it 
8490                 belongs */
8491                 if (AOP_SIZE(result) > 1 &&
8492                         !OP_SYMBOL(left)->remat &&
8493                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8494                         ic->depth )) {
8495                         int size = AOP_SIZE(result) - 1;
8496                         while (size--)
8497                                 pic14_emitcode("dec","%s",rname);
8498                 }
8499         }
8500         
8501         /* done */
8502         freeAsmop(result,NULL,ic,TRUE);
8503         
8504         
8505 }
8506
8507 /*-----------------------------------------------------------------*/
8508 /* genFarPointerGet - gget value from far space                    */
8509 /*-----------------------------------------------------------------*/
8510 static void genFarPointerGet (operand *left,
8511                                                           operand *result, iCode *ic)
8512 {
8513         int size, offset ;
8514         sym_link *retype = getSpec(operandType(result));
8515         
8516         FENTRY;
8517         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8518         
8519         aopOp(left,ic,FALSE);
8520         
8521         /* if the operand is already in dptr 
8522         then we do nothing else we move the value to dptr */
8523         if (AOP_TYPE(left) != AOP_STR) {
8524                 /* if this is remateriazable */
8525                 if (AOP_TYPE(left) == AOP_IMMD)
8526                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8527                 else { /* we need to get it byte by byte */
8528                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8529                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8530                         if (options.model == MODEL_FLAT24)
8531                         {
8532                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8533                         }
8534                 }
8535         }
8536         /* so dptr know contains the address */
8537         freeAsmop(left,NULL,ic,TRUE);
8538         aopOp(result,ic,FALSE);
8539         
8540         /* if bit then unpack */
8541         if (IS_BITFIELD(retype)) 
8542                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8543         else {
8544                 size = AOP_SIZE(result);
8545                 offset = 0 ;
8546                 
8547                 while (size--) {
8548                         pic14_emitcode("movx","a,@dptr");
8549                         aopPut(AOP(result),"a",offset++);
8550                         if (size)
8551                                 pic14_emitcode("inc","dptr");
8552                 }
8553         }
8554         
8555         freeAsmop(result,NULL,ic,TRUE);
8556 }
8557 #if 0
8558 /*-----------------------------------------------------------------*/
8559 /* genCodePointerGet - get value from code space                  */
8560 /*-----------------------------------------------------------------*/
8561 static void genCodePointerGet (operand *left,
8562                                                            operand *result, iCode *ic)
8563 {
8564         int size, offset ;
8565         sym_link *retype = getSpec(operandType(result));
8566         
8567         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8568         
8569         aopOp(left,ic,FALSE);
8570         
8571         /* if the operand is already in dptr 
8572         then we do nothing else we move the value to dptr */
8573         if (AOP_TYPE(left) != AOP_STR) {
8574                 /* if this is remateriazable */
8575                 if (AOP_TYPE(left) == AOP_IMMD)
8576                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8577                 else { /* we need to get it byte by byte */
8578                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8579                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8580                         if (options.model == MODEL_FLAT24)
8581                         {
8582                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8583                         }
8584                 }
8585         }
8586         /* so dptr know contains the address */
8587         freeAsmop(left,NULL,ic,TRUE);
8588         aopOp(result,ic,FALSE);
8589         
8590         /* if bit then unpack */
8591         if (IS_BITFIELD(retype)) 
8592                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8593         else {
8594                 size = AOP_SIZE(result);
8595                 offset = 0 ;
8596                 
8597                 while (size--) {
8598                         pic14_emitcode("clr","a");
8599                         pic14_emitcode("movc","a,@a+dptr");
8600                         aopPut(AOP(result),"a",offset++);
8601                         if (size)
8602                                 pic14_emitcode("inc","dptr");
8603                 }
8604         }
8605         
8606         freeAsmop(result,NULL,ic,TRUE);
8607 }
8608 #endif
8609 /*-----------------------------------------------------------------*/
8610 /* genGenPointerGet - gget value from generic pointer space        */
8611 /*-----------------------------------------------------------------*/
8612 static void genGenPointerGet (operand *left,
8613                                                           operand *result, iCode *ic)
8614 {
8615         int size, offset ;
8616         sym_link *retype = getSpec(operandType(result));
8617         
8618         FENTRY;
8619         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8620         aopOp(left,ic,FALSE);
8621         aopOp(result,ic,FALSE);
8622         
8623         
8624         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8625         
8626         /* if the operand is already in dptr 
8627         then we do nothing else we move the value to dptr */
8628         //  if (AOP_TYPE(left) != AOP_STR) {
8629         /* if this is remateriazable */
8630         if (AOP_TYPE(left) == AOP_IMMD) {
8631                 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8632                 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8633         }
8634         else { /* we need to get it byte by byte */
8635                 
8636                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8637                 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8638                 
8639                 size = AOP_SIZE(result);
8640                 offset = 0 ;
8641                 
8642                 while(size--) {
8643                         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8644                         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8645                         if(size)
8646                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8647                 }
8648                 goto release;
8649         }
8650         //}
8651         /* so dptr know contains the address */
8652         
8653         /* if bit then unpack */
8654         //if (IS_BITFIELD(retype)) 
8655         //  genUnpackBits(result,"dptr",GPOINTER);
8656         
8657 release:
8658         freeAsmop(left,NULL,ic,TRUE);
8659         freeAsmop(result,NULL,ic,TRUE);
8660         
8661 }
8662
8663 /*-----------------------------------------------------------------*/
8664 /* genConstPointerGet - get value from const generic pointer space */
8665 /*-----------------------------------------------------------------*/
8666 static void genConstPointerGet (operand *left,
8667                                                                 operand *result, iCode *ic)
8668 {
8669         //sym_link *retype = getSpec(operandType(result));
8670         symbol *albl, *blbl;//, *clbl;
8671         PIC_OPCODE poc;
8672         int i, size, lit;
8673         pCodeOp *pcop;
8674         
8675         FENTRY;
8676         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8677         aopOp(left,ic,FALSE);
8678         aopOp(result,ic,FALSE);
8679         
8680         size = AOP_SIZE(result);
8681         
8682         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8683         
8684         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8685
8686         lit = aop_isLitLike (AOP(left));
8687         poc = lit ? POC_MOVLW : POC_MOVFW;
8688
8689         if (lit)
8690         {
8691                 for (i = 0; i < size; i++)
8692                 {
8693                         albl = newiTempLabel(NULL);
8694                         blbl = newiTempLabel(NULL);
8695                         
8696                         emitpcode(POC_CALL,popGetLabel(albl->key));
8697                         pcop = popGetLabel(blbl->key);
8698                         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8699                         emitpcode(POC_GOTO,pcop);
8700                         
8701                         emitpLabel(albl->key);
8702                         emitpcode(poc,popGetAddr(AOP(left),1,i));
8703                         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8704                         emitpcode(poc,popGetAddr(AOP(left),0,i));
8705                         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8706                 
8707                         emitpLabel(blbl->key);
8708                         emitpcode(POC_MOVWF,popGet(AOP(result),i));
8709                 } // for
8710         } else {
8711                 albl = newiTempLabel(NULL);
8712                 blbl = newiTempLabel(NULL);
8713                 //clbl = newiTempLabel(NULL);
8714
8715                 emitpcode (POC_GOTO, popGetLabel (blbl->key));
8716                 
8717                 emitpLabel(albl->key);
8718                 emitpcode(poc,popGet(AOP(left),1));
8719                 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8720                 emitpcode(poc,popGet(AOP(left),0));
8721                 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8722                 
8723                 emitpLabel(blbl->key);
8724                 
8725                 for (i = 0; i < size; i++)
8726                 {
8727                         emitpcode(POC_CALL,popGetLabel(albl->key));
8728                         /* the next two instructions (plus clbl) might be useless... */
8729                         //pcop = popGetLabel(clbl->key);
8730                         //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8731                         //emitpcode(POC_GOTO,pcop);
8732                         //emitpLabel(clbl->key);
8733
8734                         if (i+1 < size) {
8735                                 emitpcode (POC_INCF, popGet (AOP(left), 0));
8736                                 emitSKPNZ;
8737                                 emitpcode (POC_INCF, popGet (AOP(left), 1));
8738                         }
8739                         emitpcode(POC_MOVWF,popGet(AOP(result),i));
8740                 } // for
8741                 if (size > 1) {
8742                         /* restore left's value */
8743                         emitpcode (POC_MOVLW, popGetLit (size-1));
8744                         emitpcode (POC_SUBWF, popGet (AOP(left), 0));
8745                         emitSKPC;
8746                         emitpcode (POC_DECF, popGet (AOP(left), 1));
8747                 } // if
8748         } // if (lit)
8749         
8750         freeAsmop(left,NULL,ic,TRUE);
8751         freeAsmop(result,NULL,ic,TRUE);
8752         
8753 }
8754 /*-----------------------------------------------------------------*/
8755 /* genPointerGet - generate code for pointer get                   */
8756 /*-----------------------------------------------------------------*/
8757 static void genPointerGet (iCode *ic)
8758 {
8759         operand *left, *result ;
8760         sym_link *type, *etype;
8761         int p_type = -1;
8762         
8763         FENTRY;
8764         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8765         
8766         left = IC_LEFT(ic);
8767         result = IC_RESULT(ic) ;
8768         
8769         /* depending on the type of pointer we need to
8770         move it to the correct pointer register */
8771         type = operandType(left);
8772         etype = getSpec(type);
8773         
8774         if (IS_PTR_CONST(type))
8775                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8776         
8777         /* if left is of type of pointer then it is simple */
8778         if (IS_PTR(type) && !IS_FUNC(type->next)) 
8779                 p_type = DCL_TYPE(type);
8780         else {
8781                 /* we have to go by the storage class */
8782                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8783                 
8784                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8785                 
8786                 if (SPEC_OCLS(etype)->codesp ) {
8787                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8788                         //p_type = CPOINTER ; 
8789                 }
8790                 else
8791                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8792                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8793                         /*p_type = FPOINTER ;*/ 
8794                         else
8795                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8796                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8797                                 /*        p_type = PPOINTER; */
8798                                 else
8799                                         if (SPEC_OCLS(etype) == idata )
8800                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8801                                         /*      p_type = IPOINTER; */
8802                                         else
8803                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8804                                         /*      p_type = POINTER ; */
8805         }
8806         
8807         /* now that we have the pointer type we assign
8808         the pointer values */
8809         switch (p_type) {
8810                 
8811         case POINTER: 
8812         case IPOINTER:
8813                 genNearPointerGet (left,result,ic);
8814                 break;
8815                 
8816         case PPOINTER:
8817                 genPagedPointerGet(left,result,ic);
8818                 break;
8819                 
8820         case FPOINTER:
8821                 genFarPointerGet (left,result,ic);
8822                 break;
8823                 
8824         case CPOINTER:
8825                 genConstPointerGet (left,result,ic);
8826                 //pic14_emitcodePointerGet (left,result,ic);
8827                 break;
8828                 
8829         case GPOINTER:
8830                 if (IS_CODEPTR(type) || IS_PTR_CONST(type))
8831                         genConstPointerGet (left,result,ic);
8832                 else
8833                         genGenPointerGet (left,result,ic);
8834                 break;
8835         default:
8836                 assert ( !"unhandled pointer type" );
8837                 break;
8838         }
8839         
8840 }
8841
8842 /*-----------------------------------------------------------------*/
8843 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into  */
8844 /* A through a pointer register (R0, R1, or DPTR). The original    */
8845 /* value of A can be preserved in B.                               */
8846 /* PIC has to use INDF register.                                   */
8847 /*-----------------------------------------------------------------*/
8848 static void
8849 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8850 {
8851     FENTRY;
8852     switch (p_type)
8853     {
8854     case IPOINTER:
8855     case POINTER:
8856                 if (preserveAinB)
8857                         pic14_emitcode ("mov", "b,a");
8858 //              pic14_emitcode ("mov", "a,@%s", rname);
8859                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8860                 break;
8861                 
8862     case PPOINTER:
8863                 if (preserveAinB)
8864                         pic14_emitcode ("mov", "b,a");
8865                 pic14_emitcode ("movx", "a,@%s", rname);
8866                 break;
8867                 
8868     case FPOINTER:
8869                 if (preserveAinB)
8870                         pic14_emitcode ("mov", "b,a");
8871                 pic14_emitcode ("movx", "a,@dptr");
8872                 break;
8873                 
8874     case CPOINTER:
8875                 if (preserveAinB)
8876                         pic14_emitcode ("mov", "b,a");
8877                 pic14_emitcode ("clr", "a");
8878                 pic14_emitcode ("movc", "a,@a+dptr");
8879                 break;
8880                 
8881     case GPOINTER:
8882                 if (preserveAinB)
8883         {
8884                         pic14_emitcode ("push", "b");
8885                         pic14_emitcode ("push", "acc");
8886         }
8887                 pic14_emitcode ("lcall", "__gptrget");
8888                 if (preserveAinB)
8889                         pic14_emitcode ("pop", "b");
8890                 break;
8891     }
8892 }
8893
8894 /*-----------------------------------------------------------------*/
8895 /* emitPtrByteSet - emits code to set a byte from src through a    */
8896 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8897 /*-----------------------------------------------------------------*/
8898 static void
8899 emitPtrByteSet (char *rname, int p_type, char *src)
8900 {
8901     FENTRY;
8902     switch (p_type)
8903     {
8904     case IPOINTER:
8905     case POINTER:
8906                 if (*src=='@')
8907         {
8908                         MOVA (src);
8909                         pic14_emitcode ("mov", "@%s,a", rname);
8910         }
8911                 else
8912 //                      pic14_emitcode ("mov", "@%s,%s", rname, src);
8913                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8914                 break;
8915                 
8916     case PPOINTER:
8917                 MOVA (src);
8918                 pic14_emitcode ("movx", "@%s,a", rname);
8919                 break;
8920                 
8921     case FPOINTER:
8922                 MOVA (src);
8923                 pic14_emitcode ("movx", "@dptr,a");
8924                 break;
8925                 
8926     case GPOINTER:
8927                 MOVA (src);
8928                 pic14_emitcode ("lcall", "__gptrput");
8929                 break;
8930     }
8931 }
8932
8933 /*-----------------------------------------------------------------*/
8934 /* genPackBits - generates code for packed bit storage             */
8935 /*-----------------------------------------------------------------*/
8936 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
8937 {
8938         int offset = 0;       /* source byte offset */
8939         int rlen = 0;         /* remaining bitfield length */
8940         int blen;             /* bitfield length */
8941         int bstr;             /* bitfield starting bit within byte */
8942         int litval;           /* source literal value (if AOP_LIT) */
8943         unsigned char mask;   /* bitmask within current byte */
8944
8945         FENTRY;
8946         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8947         
8948         blen = SPEC_BLEN (etype);
8949         bstr = SPEC_BSTR (etype);
8950         
8951         /* If the bitfield length is less than a byte */
8952         if (blen < 8)
8953     {
8954                 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8955                         (unsigned char) (0xFF >> (8 - bstr)));
8956                 
8957                 if (AOP_TYPE (right) == AOP_LIT)
8958         {
8959                         /* Case with a bitfield length <8 and literal source
8960                         */
8961                         int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8962                         if (blen == 1) {
8963                                 if (p_type == -1) {
8964                                         pCodeOp *pcop;
8965                                         if (AOP(result)->type == AOP_PCODE)
8966                                                 pcop = newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0);
8967                                         else
8968                                                 pcop = popGet(AOP(result),0);
8969                                         emitpcode(lit?POC_BSF:POC_BCF,pcop);
8970                                 } else {
8971                                         emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
8972                                 }
8973                                 return;
8974                         } else {
8975                                 litval = lit << bstr;
8976                                 litval &= (~mask) & 0xff;
8977                                 if (p_type == -1)
8978                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8979                                 else
8980                                         emitPtrByteGet (rname, p_type, FALSE);
8981                                 if ((mask|litval)!=0xff)
8982                                         emitpcode(POC_ANDLW,popGetLit(mask));
8983                                 if (litval)
8984                                         emitpcode(POC_IORLW,popGetLit(litval));
8985                         }
8986         }
8987                 else
8988         {
8989                         if (blen==1) {
8990                                 if (p_type == -1) {
8991                                         /* Note more efficient code, of pre clearing bit then only setting it if required, can only be done if it is known that the result is not a SFR */
8992                                         emitpcode(POC_RLF,popGet(AOP(right),0));
8993                                         emitSKPC;
8994                                         emitpcode(POC_BCF,popGet(AOP(result),0));
8995                                         emitSKPNC;
8996                                         emitpcode(POC_BSF,popGet(AOP(result),0));
8997                                 } else if (p_type!=GPOINTER) {
8998                                         /* Case with a bitfield length == 1 and no generic pointer
8999                                         */
9000                                         if (AOP_TYPE (right) == AOP_CRY)
9001                                                 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9002                                         else
9003                                         {
9004                                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9005                                                 pic14_emitcode ("rrc","a");
9006                                         }
9007                                         emitPtrByteGet (rname, p_type, FALSE);
9008                                         pic14_emitcode ("mov","acc.%d,c",bstr);
9009                                 }
9010             }
9011                         else
9012             {
9013                                 //bool pushedB;
9014                                 /* Case with a bitfield length < 8 and arbitrary source
9015                                 */
9016                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9017                                 /* shift and mask source value */
9018                                 AccLsh (right,0,bstr);
9019                                 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9020                                 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
9021                                 
9022                                 //pushedB = pushB ();
9023                                 if (p_type == -1)
9024                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9025                                 else
9026                                         emitPtrByteGet (rname, p_type, TRUE);
9027                                 
9028                                 pic14_emitcode ("anl", "a,#0x%02x", mask);
9029                                 pic14_emitcode ("orl", "a,b");
9030                                 emitpcode(POC_ANDLW,popGetLit(mask));
9031                                 emitpcode(POC_IORFW,popGet(AOP(right),0));
9032                                 if (p_type == GPOINTER)
9033                                         pic14_emitcode ("pop", "b");
9034                                 
9035                                 //popB (pushedB);
9036                         }
9037         }
9038                 
9039                 if (p_type == -1)
9040                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9041                 else
9042                         emitPtrByteSet (rname, p_type, "a");
9043                 return;
9044     }
9045         
9046         /* Bit length is greater than 7 bits. In this case, copy  */
9047         /* all except the partial byte at the end                 */
9048         for (rlen=blen;rlen>=8;rlen-=8)
9049     {
9050                 emitPtrByteSet (rname, p_type,
9051                         aopGet (AOP (right), offset++, FALSE, TRUE) );
9052                 if (rlen>8)
9053                         pic14_emitcode ("inc", "%s", rname);
9054     }
9055         
9056         /* If there was a partial byte at the end */
9057         if (rlen)
9058     {
9059                 mask = (((unsigned char) -1 << rlen) & 0xff);
9060                 
9061                 if (AOP_TYPE (right) == AOP_LIT)
9062         {
9063                 /* Case with partial byte and literal source
9064                         */
9065                         litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9066                         litval >>= (blen-rlen);
9067                         litval &= (~mask) & 0xff;
9068                         emitPtrByteGet (rname, p_type, FALSE);
9069                         if ((mask|litval)!=0xff)
9070                                 pic14_emitcode ("anl","a,#0x%02x", mask);
9071                         if (litval)
9072                                 pic14_emitcode ("orl","a,#0x%02x", litval);
9073         }
9074                 else
9075         {
9076                         //bool pushedB;
9077                         /* Case with partial byte and arbitrary source
9078                         */
9079                         MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9080                         pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9081                         
9082                         //pushedB = pushB ();
9083                         /* transfer A to B and get next byte */
9084                         emitPtrByteGet (rname, p_type, TRUE);
9085                         
9086                         pic14_emitcode ("anl", "a,#0x%02x", mask);
9087                         pic14_emitcode ("orl", "a,b");
9088                         if (p_type == GPOINTER)
9089                                 pic14_emitcode ("pop", "b");
9090                         
9091                         //popB (pushedB);
9092         }
9093                 emitPtrByteSet (rname, p_type, "a");
9094     }
9095         
9096 }
9097
9098 /*-----------------------------------------------------------------*/
9099 /* SetIrp - Set IRP bit                                            */
9100 /*-----------------------------------------------------------------*/
9101 void SetIrp(operand *result) {
9102         FENTRY;
9103         if (AOP_TYPE(result) == AOP_LIT) {
9104                 unsigned lit = (unsigned)operandLitValue(result);
9105                 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9106         } else {
9107                 if (PCOP(AOP(result))->type == PO_LITERAL) {
9108                         int addrs = PCOL(AOP(result))->lit;
9109                         emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9110                 } else {
9111                         emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
9112                         if(AOP_SIZE(result) > 1) {
9113                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9114                                 emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9115                         }
9116                 }
9117         }
9118 }
9119
9120 /*-----------------------------------------------------------------*/
9121 /* genDataPointerSet - remat pointer to data space                 */
9122 /*-----------------------------------------------------------------*/
9123 static void genDataPointerSet(operand *right,
9124         operand *result,
9125         iCode *ic)
9126 {
9127         int size, offset = 0 ;
9128         char *l, buffer[256];
9129         
9130         FENTRY;
9131         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9132         aopOp(right,ic,FALSE);
9133         
9134         l = aopGet(AOP(result),0,FALSE,TRUE);
9135         size = AOP_SIZE(right);
9136         /*
9137         if ( AOP_TYPE(result) == AOP_PCODE) {
9138         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9139         AOP(result)->aopu.pcop->name,
9140         PCOI(AOP(result)->aopu.pcop)->offset);
9141         }
9142         */
9143         
9144         // tsd, was l+1 - the underline `_' prefix was being stripped
9145         while (size--) {
9146                 emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
9147                 if (offset) {
9148                         sprintf(buffer,"(%s + %d)",l,offset);
9149                         fprintf(stderr,"%s:%i: oops  %s (%i, AOP_LIT=%i)\n",__FILE__,__LINE__,buffer, AOP_TYPE(right), AOP_LIT);
9150                 } else
9151                         sprintf(buffer,"%s",l);
9152                 
9153                 if (AOP_TYPE(right) == AOP_LIT) {
9154                         unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9155                         lit = lit >> (8*offset);
9156                         if(lit&0xff) {
9157                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9158                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9159                         } else {
9160                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9161                         }
9162                 } else {
9163                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9164                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9165                 }
9166                 
9167                 offset++;
9168         }
9169         
9170         freeAsmop(right,NULL,ic,TRUE);
9171         freeAsmop(result,NULL,ic,TRUE);
9172 }
9173
9174 /*-----------------------------------------------------------------*/
9175 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9176 /*-----------------------------------------------------------------*/
9177 static void genNearPointerSet (operand *right,
9178                                                            operand *result, 
9179                                                            iCode *ic)
9180 {
9181         asmop *aop = NULL;
9182         sym_link *ptype = operandType(result);
9183         sym_link *retype = getSpec(operandType(right));
9184         sym_link *letype = getSpec(ptype);
9185         int direct = 0;
9186         
9187         
9188         FENTRY;
9189         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9190         aopOp(result,ic,FALSE);
9191         
9192         
9193         /* if the result is rematerializable &
9194         in data space & not a bit variable */
9195         //if (AOP_TYPE(result) == AOP_IMMD &&
9196         if (AOP_TYPE(result) == AOP_PCODE &&
9197                 DCL_TYPE(ptype) == POINTER   &&
9198                 !IS_BITVAR (retype) &&
9199                 !IS_BITVAR (letype)) {
9200                 genDataPointerSet (right,result,ic);
9201                 freeAsmop(result,NULL,ic,TRUE);
9202                 return;
9203         }
9204
9205         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9206         aopOp(right,ic,FALSE);
9207         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9208         
9209         /* Check if can access directly instead of via a pointer */
9210         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9211                 direct = 1;
9212         }
9213
9214         /* If the pointer value is not in a the FSR then need to put it in */
9215         if (!AOP_INPREG(AOP(result)) && !direct) {
9216                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9217                 if (PCOP(AOP(result))->type == PO_LITERAL) 
9218                         emitpcode(POC_MOVLW, popGet(AOP(result),0));
9219                 else
9220                         emitpcode(POC_MOVFW, popGet(AOP(result),0));
9221                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
9222         }
9223
9224         /* Must set/reset IRP bit for use with FSR. */
9225         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9226         if (!direct)
9227                 SetIrp(result);
9228
9229         /* if bitfield then unpack the bits */
9230         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9231                 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
9232         } else {
9233                 /* we have can just get the values */
9234                 int size = AOP_SIZE(right);
9235                 int offset = 0 ;    
9236                 
9237                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9238                 while (size--) {
9239                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9240                         if (*l == '@' ) {
9241                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9242                         } else {
9243                                 if (AOP_TYPE(right) == AOP_LIT) {
9244                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9245                                 } else {
9246                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9247                                 }
9248                                 if (direct)
9249                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9250                                 else
9251                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9252                         }
9253                         if (size && !direct)
9254                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9255                         offset++;
9256                 }
9257         }
9258         
9259         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9260         /* now some housekeeping stuff */
9261         if (aop) {
9262                 /* we had to allocate for this iCode */
9263                 freeAsmop(NULL,aop,ic,TRUE);
9264         } else { 
9265                 /* we did not allocate which means left
9266                 already in a pointer register, then
9267                 if size > 0 && this could be used again
9268                 we have to point it back to where it 
9269                 belongs */
9270                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9271                 if (AOP_SIZE(right) > 1 &&
9272                         !OP_SYMBOL(result)->remat &&
9273                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9274                         ic->depth )) {
9275                         int size = AOP_SIZE(right) - 1;
9276                         while (size--)
9277                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9278                 }
9279         }
9280         
9281         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9282         /* done */
9283
9284         freeAsmop(right,NULL,ic,TRUE);
9285         freeAsmop(result,NULL,ic,TRUE);
9286 }
9287
9288 /*-----------------------------------------------------------------*/
9289 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9290 /*-----------------------------------------------------------------*/
9291 static void genPagedPointerSet (operand *right,
9292                                                                 operand *result, 
9293                                                                 iCode *ic)
9294 {
9295         asmop *aop = NULL;
9296         regs *preg = NULL ;
9297         char *rname , *l;
9298         sym_link *retype;
9299         
9300         FENTRY;
9301         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9302         
9303         retype= getSpec(operandType(right));
9304         
9305         aopOp(result,ic,FALSE);
9306         
9307         /* if the value is already in a pointer register
9308         then don't need anything more */
9309         if (!AOP_INPREG(AOP(result))) {
9310                 /* otherwise get a free pointer register */
9311                 aop = newAsmop(0);
9312                 preg = getFreePtr(ic,&aop,FALSE);
9313                 pic14_emitcode("mov","%s,%s",
9314                         preg->name,
9315                         aopGet(AOP(result),0,FALSE,TRUE));
9316                 rname = preg->name ;
9317         } else
9318                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9319         
9320         freeAsmop(result,NULL,ic,TRUE);
9321         aopOp (right,ic,FALSE);
9322         
9323         /* if bitfield then unpack the bits */
9324         if (IS_BITFIELD(retype)) 
9325                 genPackBits (retype,result,right,rname,PPOINTER);
9326         else {
9327                 /* we have can just get the values */
9328                 int size = AOP_SIZE(right);
9329                 int offset = 0 ;  
9330                 
9331                 while (size--) {
9332                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9333                         
9334                         MOVA(l);
9335                         pic14_emitcode("movx","@%s,a",rname);
9336                         
9337                         if (size)
9338                                 pic14_emitcode("inc","%s",rname);
9339                         
9340                         offset++;
9341                 }
9342         }
9343         
9344         /* now some housekeeping stuff */
9345         if (aop) {
9346                 /* we had to allocate for this iCode */
9347                 freeAsmop(NULL,aop,ic,TRUE);
9348         } else { 
9349         /* we did not allocate which means left
9350         already in a pointer register, then
9351         if size > 0 && this could be used again
9352         we have to point it back to where it 
9353                 belongs */
9354                 if (AOP_SIZE(right) > 1 &&
9355                         !OP_SYMBOL(result)->remat &&
9356                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9357                         ic->depth )) {
9358                         int size = AOP_SIZE(right) - 1;
9359                         while (size--)
9360                                 pic14_emitcode("dec","%s",rname);
9361                 }
9362         }
9363         
9364         /* done */
9365         freeAsmop(right,NULL,ic,TRUE);
9366         
9367         
9368 }
9369
9370 /*-----------------------------------------------------------------*/
9371 /* genFarPointerSet - set value from far space                     */
9372 /*-----------------------------------------------------------------*/
9373 static void genFarPointerSet (operand *right,
9374                                                           operand *result, iCode *ic)
9375 {
9376         int size, offset ;
9377         sym_link *retype = getSpec(operandType(right));
9378         
9379         FENTRY;
9380         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9381         aopOp(result,ic,FALSE);
9382         
9383         /* if the operand is already in dptr 
9384         then we do nothing else we move the value to dptr */
9385         if (AOP_TYPE(result) != AOP_STR) {
9386                 /* if this is remateriazable */
9387                 if (AOP_TYPE(result) == AOP_IMMD)
9388                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9389                 else { /* we need to get it byte by byte */
9390                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9391                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9392                         if (options.model == MODEL_FLAT24)
9393                         {
9394                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9395                         }
9396                 }
9397         }
9398         /* so dptr know contains the address */
9399         freeAsmop(result,NULL,ic,TRUE);
9400         aopOp(right,ic,FALSE);
9401         
9402         /* if bit then unpack */
9403         if (IS_BITFIELD(retype)) 
9404                 genPackBits(retype,result,right,"dptr",FPOINTER);
9405         else {
9406                 size = AOP_SIZE(right);
9407                 offset = 0 ;
9408                 
9409                 while (size--) {
9410                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9411                         MOVA(l);
9412                         pic14_emitcode("movx","@dptr,a");
9413                         if (size)
9414                                 pic14_emitcode("inc","dptr");
9415                 }
9416         }
9417         
9418         freeAsmop(right,NULL,ic,TRUE);
9419 }
9420
9421 /*-----------------------------------------------------------------*/
9422 /* genGenPointerSet - set value from generic pointer space         */
9423 /*-----------------------------------------------------------------*/
9424 static void genGenPointerSet (operand *right,
9425                                                           operand *result, iCode *ic)
9426 {
9427         sym_link *ptype = operandType(result);
9428         sym_link *retype = getSpec(operandType(right));
9429         sym_link *letype = getSpec (ptype);
9430         
9431         FENTRY;
9432         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9433         
9434         aopOp(result,ic,FALSE);
9435         aopOp(right,ic,FALSE);
9436         
9437         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9438         
9439         /* if the operand is already in dptr 
9440         then we do nothing else we move the value to dptr */
9441         if (AOP_TYPE(result) != AOP_STR) {
9442                 /* if this is remateriazable */
9443                 if (AOP_TYPE(result) == AOP_IMMD) {
9444                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9445                         pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9446                 }
9447                 else {
9448                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9449                         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9450
9451                         /* Must set/reset IRP bit for use with FSR. */
9452                         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9453                         SetIrp(result);
9454                 }
9455         }
9456
9457         /* if bitfield then unpack the bits */
9458         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9459                 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9460         } else {
9461                 /* we have can just get the values */
9462                 int size = AOP_SIZE(right);
9463                 int offset = 0 ;    
9464                 
9465                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9466                 while (size--) {
9467                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9468                         if (*l == '@' ) {
9469                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9470                         } else {
9471                                 if (AOP_TYPE(right) == AOP_LIT) {
9472                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9473                                 } else {
9474                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9475                                 }
9476                                 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9477                         }
9478                         if (size)
9479                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9480                         offset++;
9481                 }
9482         }
9483         
9484         freeAsmop(right,NULL,ic,TRUE);
9485         freeAsmop(result,NULL,ic,TRUE);
9486 }
9487
9488 /*-----------------------------------------------------------------*/
9489 /* genPointerSet - stores the value into a pointer location        */
9490 /*-----------------------------------------------------------------*/
9491 static void genPointerSet (iCode *ic)
9492 {    
9493         operand *right, *result ;
9494         sym_link *type, *etype;
9495         int p_type;
9496         
9497         FENTRY;
9498         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9499         
9500         right = IC_RIGHT(ic);
9501         result = IC_RESULT(ic) ;
9502         
9503         /* depending on the type of pointer we need to
9504         move it to the correct pointer register */
9505         type = operandType(result);
9506         etype = getSpec(type);
9507         /* if left is of type of pointer then it is simple */
9508         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9509                 p_type = DCL_TYPE(type);
9510         }
9511         else {
9512                 /* we have to go by the storage class */
9513                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9514                 
9515                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9516                 /*      p_type = CPOINTER ;  */
9517                 /*  } */
9518                 /*  else */
9519                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9520                 /*    p_type = FPOINTER ; */
9521                 /*      else */
9522                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9523                 /*        p_type = PPOINTER ; */
9524                 /*    else */
9525                 /*        if (SPEC_OCLS(etype) == idata ) */
9526                 /*      p_type = IPOINTER ; */
9527                 /*        else */
9528                 /*      p_type = POINTER ; */
9529         }
9530         
9531         /* now that we have the pointer type we assign
9532         the pointer values */
9533         switch (p_type) {
9534                 
9535         case POINTER:
9536         case IPOINTER:
9537                 genNearPointerSet (right,result,ic);
9538                 break;
9539                 
9540         case PPOINTER:
9541                 genPagedPointerSet (right,result,ic);
9542                 break;
9543                 
9544         case FPOINTER:
9545                 genFarPointerSet (right,result,ic);
9546                 break;
9547                 
9548         case GPOINTER:
9549                 genGenPointerSet (right,result,ic);
9550                 break;
9551                 
9552         default:
9553                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9554                         "genPointerSet: illegal pointer type");
9555         }
9556 }
9557
9558 /*-----------------------------------------------------------------*/
9559 /* genIfx - generate code for Ifx statement                        */
9560 /*-----------------------------------------------------------------*/
9561 static void genIfx (iCode *ic, iCode *popIc)
9562 {
9563         operand *cond = IC_COND(ic);
9564         int isbit =0;
9565         
9566         FENTRY;
9567         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9568         
9569         aopOp(cond,ic,FALSE);
9570         
9571         /* get the value into acc */
9572         if (AOP_TYPE(cond) != AOP_CRY)
9573                 pic14_toBoolean(cond);
9574         else
9575                 isbit = 1;
9576         /* the result is now in the accumulator */
9577         freeAsmop(cond,NULL,ic,TRUE);
9578         
9579         /* if there was something to be popped then do it */
9580         if (popIc)
9581                 genIpop(popIc);
9582         
9583         /* if the condition is  a bit variable */
9584         if (isbit && IS_ITEMP(cond) && 
9585                 SPIL_LOC(cond)) {
9586                 genIfxJump(ic,SPIL_LOC(cond)->rname);
9587                 DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9588         }
9589         else {
9590                 if (isbit && !IS_ITEMP(cond))
9591                         genIfxJump(ic,OP_SYMBOL(cond)->rname);
9592                 else
9593                         genIfxJump(ic,"a");
9594         }
9595         ic->generated = 1;
9596         
9597 }
9598
9599 /*-----------------------------------------------------------------*/
9600 /* genAddrOf - generates code for address of                       */
9601 /*-----------------------------------------------------------------*/
9602 static void genAddrOf (iCode *ic)
9603 {
9604         operand *right, *result, *left;
9605         int size, offset ;
9606         
9607         FENTRY;
9608         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9609         
9610         
9611         //aopOp(IC_RESULT(ic),ic,FALSE);
9612         
9613         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9614         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9615         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9616         
9617         DEBUGpic14_AopType(__LINE__,left,right,result);
9618         assert (IS_SYMOP (left));
9619         
9620         /* sanity check: generic pointers to code space are not yet supported,
9621          * pionters to codespace must not be assigned addresses of __data values. */
9622  #if 0
9623         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9624         fprintf (stderr, "result->type : "); printTypeChain (OP_SYM_TYPE(result), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(result)))), IS_CODEPTR(OP_SYM_TYPE(result)), IS_PTR_CONST(OP_SYM_TYPE(result)));
9625         fprintf (stderr, "result->etype: "); printTypeChain (OP_SYM_ETYPE(result), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_ETYPE(result)))), IS_CODEPTR(OP_SYM_ETYPE(result)), IS_PTR_CONST(OP_SYM_ETYPE(result)));
9626         fprintf (stderr, "left->type   : "); printTypeChain (OP_SYM_TYPE(left), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n", IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left)))), IS_CODEPTR(OP_SYM_TYPE(left)), IS_PTR_CONST(OP_SYM_TYPE(left)));
9627         fprintf (stderr, "left->etype  : "); printTypeChain (OP_SYM_ETYPE(left), stderr); fprintf (stderr, ", codesp:%d, codeptr:%d, constptr:%d\n",IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_ETYPE(left)))), IS_CODEPTR(OP_SYM_ETYPE(left)), IS_PTR_CONST(OP_SYM_ETYPE(left)));
9628 #endif
9629
9630         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9631           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9632                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9633                 OP_SYMBOL(left)->name);
9634         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9635           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9636                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9637                 OP_SYMBOL(left)->name);
9638         }
9639         
9640         size = AOP_SIZE(IC_RESULT(ic));
9641         offset = 0;
9642         
9643         while (size--) {
9644                 /* fixing bug #863624, reported from (errolv) */
9645                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9646                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9647                 
9648 #if 0
9649                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9650                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9651 #endif
9652                 offset++;
9653         }
9654         
9655         freeAsmop(left,NULL,ic,FALSE);
9656         freeAsmop(result,NULL,ic,TRUE);
9657         
9658 }
9659
9660 #if 0
9661 /*-----------------------------------------------------------------*/
9662 /* genFarFarAssign - assignment when both are in far space         */
9663 /*-----------------------------------------------------------------*/
9664 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9665 {
9666         int size = AOP_SIZE(right);
9667         int offset = 0;
9668         char *l ;
9669         /* first push the right side on to the stack */
9670         while (size--) {
9671                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9672                 MOVA(l);
9673                 pic14_emitcode ("push","acc");
9674         }
9675         
9676         freeAsmop(right,NULL,ic,FALSE);
9677         /* now assign DPTR to result */
9678         aopOp(result,ic,FALSE);
9679         size = AOP_SIZE(result);
9680         while (size--) {
9681                 pic14_emitcode ("pop","acc");
9682                 aopPut(AOP(result),"a",--offset);
9683         }
9684         freeAsmop(result,NULL,ic,FALSE);
9685         
9686 }
9687 #endif
9688
9689 /*-----------------------------------------------------------------*/
9690 /* genAssign - generate code for assignment                        */
9691 /*-----------------------------------------------------------------*/
9692 static void genAssign (iCode *ic)
9693 {
9694         operand *result, *right;
9695         int size, offset,know_W;
9696         unsigned long lit = 0L;
9697         
9698         result = IC_RESULT(ic);
9699         right  = IC_RIGHT(ic) ;
9700         
9701         FENTRY;
9702         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9703         
9704         /* if they are the same */
9705         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9706                 return ;
9707         
9708         aopOp(right,ic,FALSE);
9709         aopOp(result,ic,TRUE);
9710         
9711         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9712         
9713         /* if they are the same registers */
9714         if (pic14_sameRegs(AOP(right),AOP(result)))
9715                 goto release;
9716
9717         /* special case: assign from __code */
9718         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9719                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9720                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9721                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9722                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9723         {
9724           emitpComment ("genAssign from CODESPACE");
9725           genConstPointerGet (right, result, ic);
9726           goto release;
9727         }
9728         
9729         /* just for symmetry reasons... */
9730         if (!IS_ITEMP(result)
9731                 && IS_SYMOP (result)
9732                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9733         {
9734           assert ( !"cannot write to CODESPACE" );
9735         }
9736
9737         /* if the result is a bit */
9738         if (AOP_TYPE(result) == AOP_CRY) {
9739                 
9740         /* if the right size is a literal then
9741                 we know what the value is */
9742                 if (AOP_TYPE(right) == AOP_LIT) {
9743                         
9744                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9745                                 popGet(AOP(result),0));
9746                         
9747                         if (((int) operandLitValue(right))) 
9748                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9749                                 AOP(result)->aopu.aop_dir,
9750                                 AOP(result)->aopu.aop_dir);
9751                         else
9752                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9753                                 AOP(result)->aopu.aop_dir,
9754                                 AOP(result)->aopu.aop_dir);
9755                         goto release;
9756                 }
9757                 
9758                 /* the right is also a bit variable */
9759                 if (AOP_TYPE(right) == AOP_CRY) {
9760                         emitpcode(POC_BCF,    popGet(AOP(result),0));
9761                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9762                         emitpcode(POC_BSF,    popGet(AOP(result),0));
9763                         
9764                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9765                                 AOP(result)->aopu.aop_dir,
9766                                 AOP(result)->aopu.aop_dir);
9767                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9768                                 AOP(right)->aopu.aop_dir,
9769                                 AOP(right)->aopu.aop_dir);
9770                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9771                                 AOP(result)->aopu.aop_dir,
9772                                 AOP(result)->aopu.aop_dir);
9773                         goto release ;
9774                 }
9775                 
9776                 /* we need to or */
9777                 emitpcode(POC_BCF,    popGet(AOP(result),0));
9778                 pic14_toBoolean(right);
9779                 emitSKPZ;
9780                 emitpcode(POC_BSF,    popGet(AOP(result),0));
9781                 //aopPut(AOP(result),"a",0);
9782                 goto release ;
9783         }
9784         
9785         /* bit variables done */
9786         /* general case */
9787         size = AOP_SIZE(result);
9788         offset = 0 ;
9789         if(AOP_TYPE(right) == AOP_LIT)
9790                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9791         
9792         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9793                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9794                 if(aopIdx(AOP(result),0) == 4) {
9795                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9796                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9797                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9798                         goto release;
9799                 } else
9800                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9801         }
9802         
9803         know_W=-1;
9804         while (size--) {
9805                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9806                 if(AOP_TYPE(right) == AOP_LIT) {
9807                         if(lit&0xff) {
9808                                 if(know_W != (int)(lit&0xff))
9809                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9810                                 know_W = lit&0xff;
9811                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9812                         } else
9813                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9814                         
9815                         lit >>= 8;
9816                         
9817                 } else if (AOP_TYPE(right) == AOP_CRY) {
9818                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9819                         if(offset == 0) {
9820                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
9821                                 emitpcode(POC_INCF, popGet(AOP(result),0));
9822                         }
9823                 } else {
9824                         mov2w (AOP(right), offset);
9825                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9826                 }
9827                 
9828                 offset++;
9829         }
9830         
9831         
9832 release:
9833         freeAsmop (right,NULL,ic,FALSE);
9834         freeAsmop (result,NULL,ic,TRUE);
9835 }   
9836
9837 /*-----------------------------------------------------------------*/
9838 /* genJumpTab - genrates code for jump table                       */
9839 /*-----------------------------------------------------------------*/
9840 static void genJumpTab (iCode *ic)
9841 {
9842         symbol *jtab;
9843         char *l;
9844         
9845         FENTRY;
9846         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9847         
9848         aopOp(IC_JTCOND(ic),ic,FALSE);
9849         /* get the condition into accumulator */
9850         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9851         MOVA(l);
9852         /* multiply by three */
9853         pic14_emitcode("add","a,acc");
9854         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9855         
9856         jtab = newiTempLabel(NULL);
9857         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9858         pic14_emitcode("jmp","@a+dptr");
9859         pic14_emitcode("","%05d_DS_:",jtab->key+100);
9860         
9861         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9862         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9863         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9864         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9865         emitSKPNC;
9866         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9867         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9868         emitpLabel(jtab->key);
9869         
9870         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9871         
9872         /* now generate the jump labels */
9873         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9874         jtab = setNextItem(IC_JTLABELS(ic))) {
9875                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9876                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
9877                 
9878         }
9879         
9880 }
9881
9882 /*-----------------------------------------------------------------*/
9883 /* genMixedOperation - gen code for operators between mixed types  */
9884 /*-----------------------------------------------------------------*/
9885 /*
9886 TSD - Written for the PIC port - but this unfortunately is buggy.
9887 This routine is good in that it is able to efficiently promote 
9888 types to different (larger) sizes. Unfortunately, the temporary
9889 variables that are optimized out by this routine are sometimes
9890 used in other places. So until I know how to really parse the 
9891 iCode tree, I'm going to not be using this routine :(.
9892 */
9893 static int genMixedOperation (iCode *ic)
9894 {
9895         FENTRY;
9896 #if 0
9897         operand *result = IC_RESULT(ic);
9898         sym_link *ctype = operandType(IC_LEFT(ic));
9899         operand *right = IC_RIGHT(ic);
9900         int ret = 0;
9901         int big,small;
9902         int offset;
9903         
9904         iCode *nextic;
9905         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9906         
9907         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9908         
9909         nextic = ic->next;
9910         if(!nextic)
9911                 return 0;
9912         
9913         nextright = IC_RIGHT(nextic);
9914         nextleft  = IC_LEFT(nextic);
9915         nextresult = IC_RESULT(nextic);
9916         
9917         aopOp(right,ic,FALSE);
9918         aopOp(result,ic,FALSE);
9919         aopOp(nextright,  nextic, FALSE);
9920         aopOp(nextleft,   nextic, FALSE);
9921         aopOp(nextresult, nextic, FALSE);
9922         
9923         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9924                 
9925                 operand *t = right;
9926                 right = nextright;
9927                 nextright = t; 
9928                 
9929                 pic14_emitcode(";remove right +","");
9930                 
9931         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9932         /*
9933         operand *t = right;
9934         right = nextleft;
9935         nextleft = t; 
9936                 */
9937                 pic14_emitcode(";remove left +","");
9938         } else
9939                 return 0;
9940         
9941         big = AOP_SIZE(nextleft);
9942         small = AOP_SIZE(nextright);
9943         
9944         switch(nextic->op) {
9945                 
9946         case '+':
9947                 pic14_emitcode(";optimize a +","");
9948                 /* if unsigned or not an integral type */
9949                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9950                         pic14_emitcode(";add a bit to something","");
9951                 } else {
9952                         
9953                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9954                         
9955                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9956                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9957                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9958                         } else
9959                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9960                         
9961                         offset = 0;
9962                         while(--big) {
9963                                 
9964                                 offset++;
9965                                 
9966                                 if(--small) {
9967                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9968                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9969                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9970                                         }
9971                                         
9972                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9973                                         emitSKPNC;
9974                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9975                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9976                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9977                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9978                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9979                                         
9980                                 } else {
9981                                         pic14_emitcode("rlf","known_zero,w");
9982                                         
9983                                         /*
9984                                         if right is signed
9985                                         btfsc  right,7
9986                                         addlw ff
9987                                         */
9988                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9989                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9990                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9991                                         } else {
9992                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9993                                         }
9994                                 }
9995                         }
9996                         ret = 1;
9997                 }
9998         }
9999         ret = 1;
10000         
10001 release:
10002         freeAsmop(right,NULL,ic,TRUE);
10003         freeAsmop(result,NULL,ic,TRUE);
10004         freeAsmop(nextright,NULL,ic,TRUE);
10005         freeAsmop(nextleft,NULL,ic,TRUE);
10006         if(ret)
10007                 nextic->generated = 1;
10008         
10009         return ret;
10010 #else
10011         return 0;
10012 #endif
10013 }
10014 /*-----------------------------------------------------------------*/
10015 /* genCast - gen code for casting                                  */
10016 /*-----------------------------------------------------------------*/
10017 static void genCast (iCode *ic)
10018 {
10019         operand *result = IC_RESULT(ic);
10020         sym_link *ctype = operandType(IC_LEFT(ic));
10021         sym_link *rtype = operandType(IC_RIGHT(ic));
10022         operand *right = IC_RIGHT(ic);
10023         int size, offset ;
10024         
10025         FENTRY;
10026         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10027         /* if they are equivalent then do nothing */
10028         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10029                 return ;
10030         
10031         aopOp(right,ic,FALSE) ;
10032         aopOp(result,ic,FALSE);
10033         
10034         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10035         
10036         /* if the result is a bit */
10037         if (AOP_TYPE(result) == AOP_CRY) {
10038         /* if the right size is a literal then
10039                 we know what the value is */
10040                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10041                 if (AOP_TYPE(right) == AOP_LIT) {
10042                         
10043                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10044                                 popGet(AOP(result),0));
10045                         
10046                         if (((int) operandLitValue(right))) 
10047                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
10048                                 AOP(result)->aopu.aop_dir,
10049                                 AOP(result)->aopu.aop_dir);
10050                         else
10051                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
10052                                 AOP(result)->aopu.aop_dir,
10053                                 AOP(result)->aopu.aop_dir);
10054                         
10055                         goto release;
10056                 }
10057                 
10058                 /* the right is also a bit variable */
10059                 if (AOP_TYPE(right) == AOP_CRY) {
10060                         
10061                         emitCLRC;
10062                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10063                         
10064                         pic14_emitcode("clrc","");
10065                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10066                                 AOP(right)->aopu.aop_dir,
10067                                 AOP(right)->aopu.aop_dir);
10068                         aopPut(AOP(result),"c",0);
10069                         goto release ;
10070                 }
10071                 
10072                 /* we need to or */
10073                 if (AOP_TYPE(right) == AOP_REG) {
10074                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10075                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
10076                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10077                 }
10078                 pic14_toBoolean(right);
10079                 aopPut(AOP(result),"a",0);
10080                 goto release ;
10081         }
10082         
10083         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10084                 int offset = 1;
10085                 size = AOP_SIZE(result);
10086                 
10087                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10088                 
10089                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10090                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10091                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10092                 
10093                 while (size--)
10094                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10095                 
10096                 goto release;
10097         }
10098         
10099         /* if they are the same size : or less */
10100         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10101                 
10102                 /* if they are in the same place */
10103                 if (pic14_sameRegs(AOP(right),AOP(result)))
10104                         goto release;
10105                 
10106                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10107                 if (IS_PTR_CONST(rtype))
10108                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10109                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10110                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10111                 
10112                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10113                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10114                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10115                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10116                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10117                         if(AOP_SIZE(result) <2)
10118                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10119                         
10120                 } else {
10121                         
10122                         /* if they in different places then copy */
10123                         size = AOP_SIZE(result);
10124                         offset = 0 ;
10125                         while (size--) {
10126                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10127                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10128                                 
10129                                 //aopPut(AOP(result),
10130                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10131                                 // offset);
10132                                 
10133                                 offset++;
10134                         }
10135                 }
10136                 goto release;
10137         }
10138         
10139         
10140         /* if the result is of type pointer */
10141         if (IS_PTR(ctype)) {
10142                 
10143                 int p_type;
10144                 sym_link *type = operandType(right);
10145                 sym_link *etype = getSpec(type);
10146                 DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10147                 
10148                 /* pointer to generic pointer */
10149                 if (IS_GENPTR(ctype)) {
10150                         char *l = zero;
10151                         
10152                         if (IS_PTR(type)) 
10153                                 p_type = DCL_TYPE(type);
10154                         else {
10155                                 /* we have to go by the storage class */
10156                                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10157                                 
10158                                 /*    if (SPEC_OCLS(etype)->codesp )  */
10159                                 /*        p_type = CPOINTER ;  */
10160                                 /*    else */
10161                                 /*        if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10162                                 /*      p_type = FPOINTER ; */
10163                                 /*        else */
10164                                 /*      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10165                                 /*          p_type = PPOINTER; */
10166                                 /*      else */
10167                                 /*          if (SPEC_OCLS(etype) == idata ) */
10168                                 /*        p_type = IPOINTER ; */
10169                                 /*          else */
10170                                 /*        p_type = POINTER ; */
10171                         }
10172                         
10173                         /* the first two bytes are known */
10174                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10175                         size = GPTRSIZE - 1; 
10176                         offset = 0 ;
10177                         while (size--) {
10178                                 if(offset < AOP_SIZE(right)) {
10179                                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10180                                         if ((AOP_TYPE(right) == AOP_PCODE) && 
10181                                                 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10182                                                 emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
10183                                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10184                                         } else { 
10185                                                 aopPut(AOP(result),
10186                                                         aopGet(AOP(right),offset,FALSE,FALSE),
10187                                                         offset);
10188                                         }
10189                                 } else 
10190                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
10191                                 offset++;
10192                         }
10193                         /* the last byte depending on type */
10194                         switch (p_type) {
10195                         case IPOINTER:
10196                         case POINTER:
10197                                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
10198                                 break;
10199                         case FPOINTER:
10200                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10201                                 l = one;
10202                                 break;
10203                         case CPOINTER:
10204                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10205                                 l = "#0x02";
10206                                 break;        
10207                         case PPOINTER:
10208                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10209                                 l = "#0x03";
10210                                 break;
10211                                 
10212                         default:
10213                                 /* this should never happen */
10214                                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10215                                         "got unknown pointer type");
10216                                 exit(1);
10217                         }
10218                         //aopPut(AOP(result),l, GPTRSIZE - 1);      
10219                         goto release ;
10220                 }
10221                 
10222                 /* just copy the pointers */
10223                 size = AOP_SIZE(result);
10224                 offset = 0 ;
10225                 while (size--) {
10226                         aopPut(AOP(result),
10227                                 aopGet(AOP(right),offset,FALSE,FALSE),
10228                                 offset);
10229                         offset++;
10230                 }
10231                 goto release ;
10232         }
10233         
10234         
10235         
10236         /* so we now know that the size of destination is greater
10237         than the size of the source.
10238         Now, if the next iCode is an operator then we might be
10239         able to optimize the operation without performing a cast.
10240         */
10241         if(genMixedOperation(ic))
10242                 goto release;
10243         
10244         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10245         
10246         /* we move to result for the size of source */
10247         size = AOP_SIZE(right);
10248         offset = 0 ;
10249         while (size--) {
10250                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10251                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10252                 offset++;
10253         }
10254         
10255         /* now depending on the sign of the destination */
10256         size = AOP_SIZE(result) - AOP_SIZE(right);
10257         /* if unsigned or not an integral type */
10258         if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10259                 while (size--)
10260                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10261         } else {
10262                 /* we need to extend the sign :{ */
10263                 
10264                 if(size == 1) {
10265                         /* Save one instruction of casting char to int */
10266                         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
10267                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10268                         emitpcode(POC_DECF,   popGet(AOP(result),offset));
10269                 } else {
10270                         emitpcodeNULLop(POC_CLRW);
10271                         
10272                         if(offset)
10273                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10274                         else
10275                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10276                         
10277                         emitpcode(POC_MOVLW,   popGetLit(0xff));
10278                         
10279                         while (size--)
10280                                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
10281                 }
10282         }
10283         
10284 release:
10285         freeAsmop(right,NULL,ic,TRUE);
10286         freeAsmop(result,NULL,ic,TRUE);
10287         
10288 }
10289
10290 /*-----------------------------------------------------------------*/
10291 /* genDjnz - generate decrement & jump if not zero instrucion      */
10292 /*-----------------------------------------------------------------*/
10293 static int genDjnz (iCode *ic, iCode *ifx)
10294 {
10295         symbol *lbl, *lbl1;
10296         FENTRY;
10297         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10298         
10299         if (!ifx)
10300                 return 0;
10301         
10302                 /* if the if condition has a false label
10303         then we cannot save */
10304         if (IC_FALSE(ifx))
10305                 return 0;
10306         
10307                 /* if the minus is not of the form 
10308         a = a - 1 */
10309         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10310                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10311                 return 0;
10312         
10313         if (operandLitValue(IC_RIGHT(ic)) != 1)
10314                 return 0;
10315         
10316                 /* if the size of this greater than one then no
10317         saving */
10318         if (getSize(operandType(IC_RESULT(ic))) > 1)
10319                 return 0;
10320         
10321         /* otherwise we can save BIG */
10322         lbl = newiTempLabel(NULL);
10323         lbl1= newiTempLabel(NULL);
10324         
10325         aopOp(IC_RESULT(ic),ic,FALSE);
10326         
10327         if (IS_AOP_PREG(IC_RESULT(ic))) {
10328                 pic14_emitcode("dec","%s",
10329                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10330                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10331                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10332         } else {  
10333                 
10334                 
10335                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10336                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10337                 
10338                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10339                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10340                 
10341         }
10342         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10343         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10344         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10345         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10346         
10347         
10348         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10349         ifx->generated = 1;
10350         return 1;
10351 }
10352
10353 /*-----------------------------------------------------------------*/
10354 /* genReceive - generate code for a receive iCode                  */
10355 /*-----------------------------------------------------------------*/
10356 static void genReceive (iCode *ic)
10357 {
10358         FENTRY;
10359         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10360         
10361         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10362                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10363                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10364                 
10365                 int size = getSize(operandType(IC_RESULT(ic)));
10366                 int offset =  fReturnSizePic - size;
10367                 while (size--) {
10368                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10369                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10370                         offset++;
10371                 }
10372                 aopOp(IC_RESULT(ic),ic,FALSE);
10373                 size = AOP_SIZE(IC_RESULT(ic));
10374                 offset = 0;
10375                 while (size--) {
10376                         pic14_emitcode ("pop","acc");
10377                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10378                 }
10379                 
10380         } else {
10381                 _G.accInUse++;
10382                 aopOp(IC_RESULT(ic),ic,FALSE);
10383                 _G.accInUse--;
10384                 assignResultValue(IC_RESULT(ic));
10385         }
10386         
10387         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10388 }
10389
10390 /*-----------------------------------------------------------------*/
10391 /* genDummyRead - generate code for dummy read of volatiles        */
10392 /*-----------------------------------------------------------------*/
10393 static void
10394 genDummyRead (iCode * ic)
10395 {
10396         FENTRY;
10397         pic14_emitcode ("; genDummyRead","");
10398         pic14_emitcode ("; not implemented","");
10399         
10400         ic = ic;
10401 }
10402
10403 /*-----------------------------------------------------------------*/
10404 /* genpic14Code - generate code for pic14 based controllers        */
10405 /*-----------------------------------------------------------------*/
10406 /*
10407 * At this point, ralloc.c has gone through the iCode and attempted
10408 * to optimize in a way suitable for a PIC. Now we've got to generate
10409 * PIC instructions that correspond to the iCode.
10410 *
10411 * Once the instructions are generated, we'll pass through both the
10412 * peep hole optimizer and the pCode optimizer.
10413 *-----------------------------------------------------------------*/
10414
10415 void genpic14Code (iCode *lic)
10416 {
10417         iCode *ic;
10418         int cln = 0;
10419         const char *cline;
10420         
10421         FENTRY;
10422         lineHead = lineCurr = NULL;
10423         
10424         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10425         addpBlock(pb);
10426         
10427         /* if debug information required */
10428         if (options.debug && currFunc) { 
10429                 if (currFunc) {
10430                         debugFile->writeFunction (currFunc, lic);
10431                 }
10432         }
10433         
10434         
10435         for (ic = lic ; ic ; ic = ic->next ) {
10436                 
10437                 //DEBUGpic14_emitcode(";ic","");
10438                 //fprintf (stderr, "in ic loop\n");
10439                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10440                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10441                 
10442                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10443                   cln = ic->lineno;
10444                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10445                   cline = printCLine (ic->filename, ic->lineno);
10446                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10447                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10448                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10449                 }
10450                 
10451                 if (options.iCodeInAsm) {
10452                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10453                 }
10454                 /* if the result is marked as
10455                 spilt and rematerializable or code for
10456                 this has already been generated then
10457                 do nothing */
10458                 if (resultRemat(ic) || ic->generated ) 
10459                         continue ;
10460                 
10461                 /* depending on the operation */
10462                 switch (ic->op) {
10463                 case '!' :
10464                         genNot(ic);
10465                         break;
10466                         
10467                 case '~' :
10468                         genCpl(ic);
10469                         break;
10470                         
10471                 case UNARYMINUS:
10472                         genUminus (ic);
10473                         break;
10474                         
10475                 case IPUSH:
10476                         genIpush (ic);
10477                         break;
10478                         
10479                 case IPOP:
10480                         /* IPOP happens only when trying to restore a 
10481                         spilt live range, if there is an ifx statement
10482                         following this pop then the if statement might
10483                         be using some of the registers being popped which
10484                         would destory the contents of the register so
10485                         we need to check for this condition and handle it */
10486                         if (ic->next            && 
10487                                 ic->next->op == IFX &&
10488                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10489                                 genIfx (ic->next,ic);
10490                         else
10491                                 genIpop (ic);
10492                         break; 
10493                         
10494                 case CALL:
10495                         genCall (ic);
10496                         break;
10497                         
10498                 case PCALL:
10499                         genPcall (ic);
10500                         break;
10501                         
10502                 case FUNCTION:
10503                         genFunction (ic);
10504                         break;
10505                         
10506                 case ENDFUNCTION:
10507                         genEndFunction (ic);
10508                         break;
10509                         
10510                 case RETURN:
10511                         genRet (ic);
10512                         break;
10513                         
10514                 case LABEL:
10515                         genLabel (ic);
10516                         break;
10517                         
10518                 case GOTO:
10519                         genGoto (ic);
10520                         break;
10521                         
10522                 case '+' :
10523                         genPlus (ic) ;
10524                         break;
10525                         
10526                 case '-' :
10527                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10528                                 genMinus (ic);
10529                         break;
10530                         
10531                 case '*' :
10532                         genMult (ic);
10533                         break;
10534                         
10535                 case '/' :
10536                         genDiv (ic) ;
10537                         break;
10538                         
10539                 case '%' :
10540                         genMod (ic);
10541                         break;
10542                         
10543                 case '>' :
10544                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10545                         break;
10546                         
10547                 case '<' :
10548                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10549                         break;
10550                         
10551                 case LE_OP:
10552                 case GE_OP:
10553                 case NE_OP:
10554                         
10555                         /* note these two are xlated by algebraic equivalence
10556                         during parsing SDCC.y */
10557                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10558                                 "got '>=' or '<=' shouldn't have come here");
10559                         break;  
10560                         
10561                 case EQ_OP:
10562                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10563                         break;      
10564                         
10565                 case AND_OP:
10566                         genAndOp (ic);
10567                         break;
10568                         
10569                 case OR_OP:
10570                         genOrOp (ic);
10571                         break;
10572                         
10573                 case '^' :
10574                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10575                         break;
10576                         
10577                 case '|' :
10578                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10579                         break;
10580                         
10581                 case BITWISEAND:
10582                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10583                         break;
10584                         
10585                 case INLINEASM:
10586                         genInline (ic);
10587                         break;
10588                         
10589                 case RRC:
10590                         genRRC (ic);
10591                         break;
10592                         
10593                 case RLC:
10594                         genRLC (ic);
10595                         break;
10596                         
10597                 case GETHBIT:
10598                         genGetHbit (ic);
10599                         break;
10600                         
10601                 case LEFT_OP:
10602                         genLeftShift (ic);
10603                         break;
10604                         
10605                 case RIGHT_OP:
10606                         genRightShift (ic);
10607                         break;
10608                         
10609                 case GET_VALUE_AT_ADDRESS:
10610                         genPointerGet(ic);
10611                         break;
10612                         
10613                 case '=' :
10614                         if (POINTER_SET(ic))
10615                                 genPointerSet(ic);
10616                         else
10617                                 genAssign(ic);
10618                         break;
10619                         
10620                 case IFX:
10621                         genIfx (ic,NULL);
10622                         break;
10623                         
10624                 case ADDRESS_OF:
10625                         genAddrOf (ic);
10626                         break;
10627                         
10628                 case JUMPTABLE:
10629                         genJumpTab (ic);
10630                         break;
10631                         
10632                 case CAST:
10633                         genCast (ic);
10634                         break;
10635                         
10636                 case RECEIVE:
10637                         genReceive(ic);
10638                         break;
10639                         
10640                 case SEND:
10641                         addSet(&_G.sendSet,ic);
10642                         break;
10643                         
10644                 case DUMMY_READ_VOLATILE:
10645                         genDummyRead (ic);
10646                         break;
10647                         
10648                 default :
10649                         ic = ic;
10650                 }
10651         }
10652
10653         
10654         /* now we are ready to call the
10655         peep hole optimizer */
10656         if (!options.nopeep) {
10657                 peepHole (&lineHead);
10658         }
10659         /* now do the actual printing */
10660         printLine (lineHead,codeOutFile);
10661         
10662 #ifdef PCODE_DEBUG
10663         DFPRINTF((stderr,"printing pBlock\n\n"));
10664         printpBlock(stdout,pb);
10665 #endif
10666         
10667         return;
10668 }
10669
10670 int
10671 aop_isLitLike (asmop *aop)
10672 {
10673   assert (aop);
10674   if (aop->type == AOP_LIT) return 1;
10675   if (aop->type == AOP_IMMD) return 1;
10676   if ((aop->type == AOP_PCODE) &&
10677                 ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
10678   {
10679     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10680      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10681     return 1;
10682   }
10683   return 0;
10684 }
10685
10686 int
10687 op_isLitLike (operand *op)
10688 {
10689   assert (op);
10690   if (aop_isLitLike (AOP(op))) return 1;
10691   return 0;
10692 }