* src/pic/gen.c (aopOp): do not generate AOP_ACC operands as pic14
[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 0
857                 /* WREG is not usable as an ordinary operand with PIC architecture,
858                  * one might introduce a scratch register that can be used to make
859                  * WREG accesible as an operand... disable WREG for now */
860                 if (sym->accuse) {
861                         int i;
862                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
863                         aop->size = getSize(sym->type);
864                         for ( i = 0 ; i < 2 ; i++ )
865                                 aop->aopu.aop_str[i] = accUse[i];
866                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
867                         return;  
868                 }
869 #endif
870                 
871                 if (sym->ruonly ) {
872                         if(sym->isptr) {        // && sym->uptr 
873                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
874                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
875                                 
876                                 //PCOI(aop->aopu.pcop)->_const = 0;
877                                 //PCOI(aop->aopu.pcop)->index = 0;
878                                 /*
879                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
880                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
881                                 */
882                                 //allocDirReg (IC_LEFT(ic));
883                                 
884                                 aop->size = getSize(sym->type);
885                                 DEBUGpic14_emitcode(";","%d",__LINE__);
886                                 return;
887                                 
888                         } else {
889                                 
890                                 unsigned i;
891                                 
892                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
893                                 aop->size = getSize(sym->type);
894                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
895                                         aop->aopu.aop_str[i] = fReturn[i];
896                                 
897                                 DEBUGpic14_emitcode(";","%d",__LINE__);
898                                 return;
899                         }
900                 }
901                 
902                 /* else spill location  */
903                 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
904                         /* force a new aop if sizes differ */
905                         sym->usl.spillLoc->aop = NULL;
906                 }
907                 DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
908                         __FUNCTION__,__LINE__,
909                         sym->usl.spillLoc->rname,
910                         sym->rname, sym->usl.spillLoc->offset);
911                 
912                 sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
913                 //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
914                 aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
915                         getSize(sym->type), 
916                         sym->usl.spillLoc->offset);
917                 aop->size = getSize(sym->type);
918                 
919                 return;
920         }
921         
922         {
923                 sym_link *type = operandType(op);
924                 if(IS_PTR_CONST(type)) 
925                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
926         }
927         
928         /* must be in a register */
929         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
930         sym->aop = op->aop = aop = newAsmop(AOP_REG);
931         aop->size = sym->nRegs;
932         for ( i = 0 ; i < sym->nRegs ;i++)
933                 aop->aopu.aop_reg[i] = sym->regs[i];
934 }
935
936 /*-----------------------------------------------------------------*/
937 /* freeAsmop - free up the asmop given to an operand                       */
938 /*----------------------------------------------------------------*/
939 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
940 {       
941         asmop *aop ;
942         
943         if (!op)
944                 aop = aaop;
945         else 
946                 aop = op->aop;
947         
948         if (!aop)
949                 return ;
950         
951         if (aop->freed)
952                 goto dealloc; 
953         
954         aop->freed = 1;
955         
956         /* depending on the asmop type only three cases need work AOP_RO
957         , AOP_R1 && AOP_STK */
958 #if 0
959         switch (aop->type) {
960         case AOP_R0 :
961                 if (_G.r0Pushed ) {
962                         if (pop) {
963                                 pic14_emitcode ("pop","ar0");     
964                                 _G.r0Pushed--;
965                         }
966                 }
967                 bitVectUnSetBit(ic->rUsed,R0_IDX);
968                 break;
969                 
970         case AOP_R1 :
971                 if (_G.r1Pushed ) {
972                         if (pop) {
973                                 pic14_emitcode ("pop","ar1");
974                                 _G.r1Pushed--;
975                         }
976                 }
977                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
978                 break;
979                 
980         case AOP_STK :
981                 {
982                         int sz = aop->size;      
983                         int stk = aop->aopu.aop_stk + aop->size;
984                         bitVectUnSetBit(ic->rUsed,R0_IDX);
985                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
986                         
987                         getFreePtr(ic,&aop,FALSE);
988                         
989                         if (options.stack10bit)
990                         {
991                                 /* I'm not sure what to do here yet... */
992                                 /* #STUB */
993                                 fprintf(stderr, 
994                                         "*** Warning: probably generating bad code for "
995                                         "10 bit stack mode.\n");
996                         }
997                         
998                         if (stk) {
999                                 pic14_emitcode ("mov","a,_bp");
1000                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1001                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1002                         } else {
1003                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1004                         }
1005                         
1006                         while (sz--) {
1007                                 pic14_emitcode("pop","acc");
1008                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1009                                 if (!sz) break;
1010                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1011                         }
1012                         op->aop = aop;
1013                         freeAsmop(op,NULL,ic,TRUE);
1014                         if (_G.r0Pushed) {
1015                                 pic14_emitcode("pop","ar0");
1016                                 _G.r0Pushed--;
1017                         }
1018                         
1019                         if (_G.r1Pushed) {
1020                                 pic14_emitcode("pop","ar1");
1021                                 _G.r1Pushed--;
1022                         }         
1023                 }
1024         }
1025 #endif
1026         
1027 dealloc:
1028         /* all other cases just dealloc */
1029         if (op ) {
1030                 op->aop = NULL;
1031                 if (IS_SYMOP(op)) {
1032                         OP_SYMBOL(op)->aop = NULL;      
1033                         /* if the symbol has a spill */
1034                         if (SPIL_LOC(op))
1035                                 SPIL_LOC(op)->aop = NULL;
1036                 }
1037         }
1038 }
1039
1040 /*-----------------------------------------------------------------*/
1041 /* aopGet - for fetching value of the aop                                                  */
1042 /*-----------------------------------------------------------------*/
1043 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1044 {
1045         char *s = buffer ;
1046         char *rs;
1047         
1048         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1049         /* offset is greater than
1050         size then zero */
1051         if (offset > (aop->size - 1) &&
1052                 aop->type != AOP_LIT)
1053                 return zero;
1054         
1055         /* depending on type */
1056         switch (aop->type) {
1057                 
1058         case AOP_R0:
1059         case AOP_R1:
1060                 DEBUGpic14_emitcode(";","%d",__LINE__);
1061                 /* if we need to increment it */           
1062                 while (offset > aop->coff) {            
1063                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1064                         aop->coff++;
1065                 }
1066                 
1067                 while (offset < aop->coff) {
1068                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1069                         aop->coff--;
1070                 }
1071                 
1072                 aop->coff = offset ;
1073                 if (aop->paged) {
1074                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1075                         return (dname ? "acc" : "a");
1076                 }               
1077                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1078                 rs = Safe_calloc(1,strlen(s)+1);
1079                 strcpy(rs,s);   
1080                 return rs;
1081                 
1082         case AOP_DPTR:
1083         case AOP_DPTR2:
1084                 DEBUGpic14_emitcode(";","%d",__LINE__);
1085                 if (aop->type == AOP_DPTR2)
1086                 {
1087                         genSetDPTR(1);
1088                 }
1089                 
1090                 while (offset > aop->coff) {
1091                         pic14_emitcode ("inc","dptr");
1092                         aop->coff++;
1093                 }
1094                 
1095                 while (offset < aop->coff) {            
1096                         pic14_emitcode("lcall","__decdptr");
1097                         aop->coff--;
1098                 }
1099                 
1100                 aop->coff = offset;
1101                 if (aop->code) {
1102                         pic14_emitcode("clr","a");
1103                         pic14_emitcode("movc","a,@a+dptr");
1104                 }
1105                 else {
1106                         pic14_emitcode("movx","a,@dptr");
1107                 }
1108                 
1109                 if (aop->type == AOP_DPTR2)
1110                 {
1111                         genSetDPTR(0);
1112                 }
1113                 
1114                 return (dname ? "acc" : "a");
1115                 
1116                 
1117         case AOP_IMMD:
1118                 if (bit16) 
1119                         sprintf (s,"%s",aop->aopu.aop_immd);
1120                 else
1121                         if (offset) 
1122                                 sprintf(s,"(%s >> %d)",
1123                                 aop->aopu.aop_immd,
1124                                 offset*8);
1125                         else
1126                                 sprintf(s,"%s",
1127                                 aop->aopu.aop_immd);
1128                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1129                         rs = Safe_calloc(1,strlen(s)+1);
1130                         strcpy(rs,s);   
1131                         return rs;
1132                         
1133         case AOP_DIR:
1134                 if (offset) {
1135                         sprintf(s,"(%s + %d)",
1136                                 aop->aopu.aop_dir,
1137                                 offset);
1138                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1139                 } else
1140                         sprintf(s,"%s",aop->aopu.aop_dir);
1141                 rs = Safe_calloc(1,strlen(s)+1);
1142                 strcpy(rs,s);   
1143                 return rs;
1144                 
1145         case AOP_REG:
1146                 //if (dname) 
1147                 //        return aop->aopu.aop_reg[offset]->dname;
1148                 //else
1149                 return aop->aopu.aop_reg[offset]->name;
1150                 
1151         case AOP_CRY:
1152                 //pic14_emitcode(";","%d",__LINE__);
1153                 return aop->aopu.aop_dir;
1154                 
1155         case AOP_ACC:
1156                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1157                 return "AOP_accumulator_bug";
1158                 
1159         case AOP_LIT:
1160                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1161                 rs = Safe_calloc(1,strlen(s)+1);
1162                 strcpy(rs,s);   
1163                 return rs;
1164                 
1165         case AOP_STR:
1166                 aop->coff = offset ;
1167                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1168                         dname)
1169                         return "acc";
1170                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1171                 
1172                 return aop->aopu.aop_str[offset];
1173                 
1174         case AOP_PCODE:
1175                 {
1176                         pCodeOp *pcop = aop->aopu.pcop;
1177                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1178                         if(pcop->name) {
1179                                 if (offset) {
1180                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1181                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1182                                 } else {
1183                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1184                                         sprintf(s,"%s", pcop->name);
1185                                 }
1186                         } else
1187                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1188                         
1189                 }
1190                 rs = Safe_calloc(1,strlen(s)+1);
1191                 strcpy(rs,s);   
1192                 return rs;
1193                 
1194   }
1195   
1196   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1197           "aopget got unsupported aop->type");
1198   exit(0);
1199 }
1200
1201
1202 /*-----------------------------------------------------------------*/
1203 /* popGetTempReg - create a new temporary pCodeOp                                  */
1204 /*-----------------------------------------------------------------*/
1205 pCodeOp *popGetTempReg(void)
1206 {
1207         
1208         pCodeOp *pcop;
1209         
1210         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1211         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1212                 PCOR(pcop)->r->wasUsed=1;
1213                 PCOR(pcop)->r->isFree=0;
1214         }
1215         
1216         return pcop;
1217 }
1218
1219 /*-----------------------------------------------------------------*/
1220 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1221 /*-----------------------------------------------------------------*/
1222 void popReleaseTempReg(pCodeOp *pcop)
1223 {
1224         
1225         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1226                 PCOR(pcop)->r->isFree = 1;
1227         
1228 }
1229 /*-----------------------------------------------------------------*/
1230 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1231 /*-----------------------------------------------------------------*/
1232 pCodeOp *popGetLabel(unsigned int key)
1233 {
1234         
1235         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1236         
1237         if(key>(unsigned int)max_key)
1238                 max_key = key;
1239         
1240         return newpCodeOpLabel(NULL,key+100+labelOffset);
1241 }
1242
1243 /*-------------------------------------------------------------------*/
1244 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1245 /*-------------------------------------------------------------------*/
1246 pCodeOp *popGetHighLabel(unsigned int key)
1247 {
1248         pCodeOp *pcop;
1249         pcop = popGetLabel(key);
1250         PCOLAB(pcop)->offset = 1;
1251         return pcop;
1252 }
1253
1254 /*-----------------------------------------------------------------*/
1255 /* popGetLit - asm operator to pcode operator conversion                           */
1256 /*-----------------------------------------------------------------*/
1257 pCodeOp *popGetLit(unsigned int lit)
1258 {
1259         
1260         return newpCodeOpLit(lit);
1261 }
1262
1263 /*-----------------------------------------------------------------*/
1264 /* popGetImmd - asm operator to pcode immediate conversion                 */
1265 /*-----------------------------------------------------------------*/
1266 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1267 {
1268         
1269         return newpCodeOpImmd(name, offset,index, 0, is_func);
1270 }
1271
1272
1273 /*-----------------------------------------------------------------*/
1274 /* popGetWithString - asm operator to pcode operator conversion                    */
1275 /*-----------------------------------------------------------------*/
1276 pCodeOp *popGetWithString(char *str, int isExtern)
1277 {
1278         pCodeOp *pcop;
1279         
1280         
1281         if(!str) {
1282                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1283                 exit (1);
1284         }
1285         
1286         pcop = newpCodeOp(str,PO_STR);
1287         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1288         
1289         return pcop;
1290 }
1291
1292 /*-----------------------------------------------------------------*/
1293 /* popRegFromString -                                                                                      */
1294 /*-----------------------------------------------------------------*/
1295 pCodeOp *popRegFromString(char *str, int size, int offset)
1296 {
1297         
1298         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1299         pcop->type = PO_DIR;
1300         
1301         DEBUGpic14_emitcode(";","%d",__LINE__);
1302         
1303         if(!str)
1304                 str = "BAD_STRING";
1305         
1306         pcop->name = Safe_calloc(1,strlen(str)+1);
1307         strcpy(pcop->name,str);
1308         
1309         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1310         
1311         PCOR(pcop)->r = dirregWithName(pcop->name);
1312         if(PCOR(pcop)->r == NULL) {
1313                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1314                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1315                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1316         } else {
1317                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1318         }
1319         PCOR(pcop)->instance = offset;
1320         
1321         return pcop;
1322 }
1323
1324 /*-----------------------------------------------------------------*/
1325 /*-----------------------------------------------------------------*/
1326 pCodeOp *popRegFromIdx(int rIdx)
1327 {
1328         pCodeOp *pcop;
1329         
1330         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1331                 __FUNCTION__,__LINE__,rIdx);
1332         
1333         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1334         
1335         PCOR(pcop)->rIdx = rIdx;
1336         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1337         PCOR(pcop)->r->isFree = 0;
1338         PCOR(pcop)->r->wasUsed = 1;
1339         
1340         pcop->type = PCOR(pcop)->r->pc_type;
1341         
1342         
1343         return pcop;
1344 }
1345
1346 /*-----------------------------------------------------------------*/
1347 /* popGet - asm operator to pcode operator conversion                      */
1348 /*-----------------------------------------------------------------*/
1349 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1350 {
1351         //char *s = buffer ;
1352         //char *rs;
1353         
1354         pCodeOp *pcop;
1355         
1356         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1357         /* offset is greater than
1358         size then zero */
1359
1360         if (!(offset >= 0 && ((offset < aop->size) || (aop->size == 0))))
1361         {
1362           fprintf (stderr, "%s:%u: offset=%d, aop-type:%s, size:%d\n", __FILE__, __LINE__, offset, AopType (aop->type), aop->size);
1363         }
1364         assert (offset >= 0 && ((offset < aop->size) || (aop->size == 0)));
1365         
1366         /* XXX: still needed for BIT operands (AOP_CRY) */
1367         if (offset > (aop->size - 1) &&
1368                 aop->type != AOP_LIT)
1369                 return NULL;  //zero;
1370         
1371         /* depending on type */
1372         switch (aop->type) {
1373                 
1374         case AOP_R0:
1375         case AOP_R1:
1376         case AOP_DPTR:
1377         case AOP_DPTR2:
1378         case AOP_ACC:
1379                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1380                 return NULL;
1381                 
1382         case AOP_IMMD:
1383                 DEBUGpic14_emitcode(";","%d",__LINE__);
1384                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1385                 
1386         case AOP_DIR:
1387                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1388 #if 0
1389                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1390                 pcop->type = PO_DIR;
1391                 
1392                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1393                 strcpy(pcop->name,aop->aopu.aop_dir);   
1394                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1395                 if(PCOR(pcop)->r == NULL) {
1396                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1397                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1398                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1399                 } else {
1400                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1401                 }
1402                 PCOR(pcop)->instance = offset;
1403                 
1404                 return pcop;
1405 #endif
1406                 
1407         case AOP_REG:
1408                 {
1409                         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1410                         
1411                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1412                         PCOR(pcop)->rIdx = rIdx;
1413                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1414                         PCOR(pcop)->r->wasUsed=1;
1415                         PCOR(pcop)->r->isFree=0;
1416                         
1417                         PCOR(pcop)->instance = offset;
1418                         pcop->type = PCOR(pcop)->r->pc_type;
1419                         //rs = aop->aopu.aop_reg[offset]->name;
1420                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1421                         return pcop;
1422                 }
1423                 
1424         case AOP_CRY:
1425                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1426                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1427                 //if(PCOR(pcop)->r == NULL)
1428                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1429                 return pcop;
1430                 
1431         case AOP_LIT:
1432                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1433                 
1434         case AOP_STR:
1435                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1436                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1437                 /*
1438                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1439                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1440                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1441                 pcop->type = PCOR(pcop)->r->pc_type;
1442                 pcop->name = PCOR(pcop)->r->name;
1443                 
1444                   return pcop;
1445                 */
1446                 
1447         case AOP_PCODE:
1448                 pcop = NULL;
1449                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1450                         __LINE__, 
1451                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1452                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1453                 switch (aop->aopu.pcop->type)
1454                 {
1455                 case PO_IMMEDIATE:
1456                   pcop = pCodeOpCopy (aop->aopu.pcop);
1457                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1458                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1459                   PCOI(pcop)->index += offset;
1460                   //PCOI(pcop)->offset = 0;
1461                   break;
1462                 case PO_DIR:
1463                   pcop = pCodeOpCopy (aop->aopu.pcop);
1464                   PCOR(pcop)->instance = offset;
1465                   break;
1466                 default:
1467                   assert ( !"unhandled pCode type" );
1468                   break;
1469                 } // switch
1470                 return pcop;
1471         }
1472         
1473         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1474                 "popGet got unsupported aop->type");
1475         exit(0);
1476 }
1477
1478 /*-----------------------------------------------------------------*/
1479 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1480 /*              (for non-PO_IMMEDIATEs this is the same as poGet)  */
1481 /*-----------------------------------------------------------------*/
1482 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1483 {
1484   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1485   {
1486     pCodeOp *pcop = aop->aopu.pcop;
1487     pcop = pCodeOpCopy (pcop);
1488     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1489      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1490     PCOI(pcop)->offset += offset;
1491     PCOI(pcop)->index += index;
1492     return pcop;
1493   } else {
1494     return popGet (aop, offset + index);
1495   }
1496 }
1497
1498 /*-----------------------------------------------------------------*/
1499 /* aopPut - puts a string for a aop                                                        */
1500 /*-----------------------------------------------------------------*/
1501 void aopPut (asmop *aop, char *s, int offset)
1502 {
1503         char *d = buffer ;
1504         symbol *lbl ;
1505         
1506         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1507         
1508         if (aop->size && offset > ( aop->size - 1)) {
1509                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1510                         "aopPut got offset > aop->size");
1511                 exit(0);
1512         }
1513         
1514         /* will assign value to value */
1515         /* depending on where it is ofcourse */
1516         switch (aop->type) {
1517         case AOP_DIR:
1518                 if (offset) {
1519                         sprintf(d,"(%s + %d)",
1520                                 aop->aopu.aop_dir,offset);
1521                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1522                         
1523                 } else
1524                         sprintf(d,"%s",aop->aopu.aop_dir);
1525                 
1526                 if (strcmp(d,s)) {
1527                         DEBUGpic14_emitcode(";","%d",__LINE__);
1528                         if(strcmp(s,"W"))
1529                                 pic14_emitcode("movf","%s,w",s);
1530                         pic14_emitcode("movwf","%s",d);
1531                         
1532                         if(strcmp(s,"W")) {
1533                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1534                                 if(offset >= aop->size) {
1535                                         emitpcode(POC_CLRF,popGet(aop,offset));
1536                                         break;
1537                                 } else
1538                                         emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1539                         }
1540                         
1541                         emitpcode(POC_MOVWF,popGet(aop,offset));
1542                         
1543                         
1544                 }
1545                 break;
1546                 
1547         case AOP_REG:
1548                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1549                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1550                         /*
1551                         if (*s == '@'             ||
1552                         strcmp(s,"r0") == 0 ||
1553                         strcmp(s,"r1") == 0 ||
1554                         strcmp(s,"r2") == 0 ||
1555                         strcmp(s,"r3") == 0 ||
1556                         strcmp(s,"r4") == 0 ||
1557                         strcmp(s,"r5") == 0 ||
1558                         strcmp(s,"r6") == 0 || 
1559                         strcmp(s,"r7") == 0 )
1560                         pic14_emitcode("mov","%s,%s  ; %d",
1561                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1562                         else
1563                         */
1564                         
1565                         if(strcmp(s,"W")==0 )
1566                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1567                         
1568                         pic14_emitcode("movwf","%s",
1569                                 aop->aopu.aop_reg[offset]->name);
1570                         
1571                         if(strcmp(s,zero)==0) {
1572                                 emitpcode(POC_CLRF,popGet(aop,offset));
1573                                 
1574                         } else if(strcmp(s,"W")==0) {
1575                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1576                                 pcop->type = PO_GPR_REGISTER;
1577                                 
1578                                 PCOR(pcop)->rIdx = -1;
1579                                 PCOR(pcop)->r = NULL;
1580                                 
1581                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1582                                 pcop->name = Safe_strdup(s);
1583                                 emitpcode(POC_MOVFW,pcop);
1584                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1585                         } else if(strcmp(s,one)==0) {
1586                                 emitpcode(POC_CLRF,popGet(aop,offset));
1587                                 emitpcode(POC_INCF,popGet(aop,offset));
1588                         } else {
1589                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1590                         }
1591                 }
1592                 break;
1593                 
1594         case AOP_DPTR:
1595         case AOP_DPTR2:
1596                 
1597                 if (aop->type == AOP_DPTR2)
1598                 {
1599                         genSetDPTR(1);
1600                 }
1601                 
1602                 if (aop->code) {
1603                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1604                                 "aopPut writting to code space");
1605                         exit(0);
1606                 }
1607                 
1608                 while (offset > aop->coff) {
1609                         aop->coff++;
1610                         pic14_emitcode ("inc","dptr");
1611                 }
1612                 
1613                 while (offset < aop->coff) {
1614                         aop->coff-- ;
1615                         pic14_emitcode("lcall","__decdptr");
1616                 }
1617                 
1618                 aop->coff = offset;
1619                 
1620                 /* if not in accumulater */
1621                 MOVA(s);
1622                 
1623                 pic14_emitcode ("movx","@dptr,a");
1624                 
1625                 if (aop->type == AOP_DPTR2)
1626                 {
1627                         genSetDPTR(0);
1628                 }
1629                 break;
1630                 
1631         case AOP_R0:
1632         case AOP_R1:
1633                 while (offset > aop->coff) {
1634                         aop->coff++;
1635                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1636                 }
1637                 while (offset < aop->coff) {
1638                         aop->coff-- ;
1639                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1640                 }
1641                 aop->coff = offset;
1642                 
1643                 if (aop->paged) {
1644                         MOVA(s);                         
1645                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1646                         
1647                 } else
1648                         if (*s == '@') {
1649                                 MOVA(s);
1650                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1651                         } else
1652                                 if (strcmp(s,"r0") == 0 ||
1653                                         strcmp(s,"r1") == 0 ||
1654                                         strcmp(s,"r2") == 0 ||
1655                                         strcmp(s,"r3") == 0 ||
1656                                         strcmp(s,"r4") == 0 ||
1657                                         strcmp(s,"r5") == 0 ||
1658                                         strcmp(s,"r6") == 0 || 
1659                                         strcmp(s,"r7") == 0 ) {
1660                                         char buffer[10];
1661                                         sprintf(buffer,"a%s",s);
1662                                         pic14_emitcode("mov","@%s,%s",
1663                                                 aop->aopu.aop_ptr->name,buffer);
1664                                 } else
1665                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1666                                 
1667                                 break;
1668                                 
1669         case AOP_STK:
1670                 if (strcmp(s,"a") == 0)
1671                         pic14_emitcode("push","acc");
1672                 else
1673                         pic14_emitcode("push","%s",s);
1674                 
1675                 break;
1676                 
1677         case AOP_CRY:
1678                 /* if bit variable */
1679                 if (!aop->aopu.aop_dir) {
1680                         pic14_emitcode("clr","a");
1681                         pic14_emitcode("rlc","a");
1682                 } else {
1683                         if (s == zero) 
1684                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1685                         else
1686                                 if (s == one)
1687                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1688                                 else
1689                                         if (!strcmp(s,"c"))
1690                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1691                                         else {
1692                                                 lbl = newiTempLabel(NULL);
1693                                                 
1694                                                 if (strcmp(s,"a")) {
1695                                                         MOVA(s);
1696                                                 }
1697                                                 pic14_emitcode("clr","c");
1698                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1699                                                 pic14_emitcode("cpl","c");
1700                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1701                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1702                                         }
1703                 }
1704                 break;
1705                 
1706         case AOP_STR:
1707                 aop->coff = offset;
1708                 if (strcmp(aop->aopu.aop_str[offset],s))
1709                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1710                 break;
1711                 
1712         case AOP_ACC:
1713                 aop->coff = offset;
1714                 if (!offset && (strcmp(s,"acc") == 0))
1715                         break;
1716                 
1717                 if (strcmp(aop->aopu.aop_str[offset],s))
1718                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1719                 break;
1720                 
1721         default :
1722                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1723                         "aopPut got unsupported aop->type");
1724                 exit(0);
1725         }
1726         
1727 }
1728
1729 /*-----------------------------------------------------------------*/
1730 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1731 /*-----------------------------------------------------------------*/
1732 void mov2w (asmop *aop, int offset)
1733 {
1734         
1735         if(!aop)
1736                 return;
1737         
1738         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1739         
1740         if ( aop_isLitLike (aop) )
1741                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1742         else
1743                 emitpcode(POC_MOVFW,popGet(aop,offset));
1744         
1745 }
1746
1747 /*-----------------------------------------------------------------*/
1748 /* reAdjustPreg - points a register back to where it should        */
1749 /*-----------------------------------------------------------------*/
1750 static void reAdjustPreg (asmop *aop)
1751 {
1752         int size ;
1753         
1754         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1755         aop->coff = 0;
1756         if ((size = aop->size) <= 1)
1757                 return ;
1758         size-- ;
1759         switch (aop->type) {
1760         case AOP_R0 :
1761         case AOP_R1 :
1762                 while (size--)
1763                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1764                 break;                  
1765         case AOP_DPTR :
1766         case AOP_DPTR2:
1767                 if (aop->type == AOP_DPTR2)
1768                 {
1769                         genSetDPTR(1);
1770                 } 
1771                 while (size--)
1772                 {
1773                         pic14_emitcode("lcall","__decdptr");
1774                 }
1775                 
1776                 if (aop->type == AOP_DPTR2)
1777                 {
1778                         genSetDPTR(0);
1779                 }
1780                 break;
1781                 
1782         }
1783         
1784 }
1785
1786
1787 #if 0
1788 /*-----------------------------------------------------------------*/
1789 /* opIsGptr: returns non-zero if the passed operand is             */
1790 /* a generic pointer type.                                         */
1791 /*-----------------------------------------------------------------*/ 
1792 static int opIsGptr(operand *op)
1793 {
1794         sym_link *type = operandType(op);
1795         
1796         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1797         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1798         {
1799                 return 1;
1800         }
1801         return 0;          
1802 }
1803 #endif
1804
1805 /*-----------------------------------------------------------------*/
1806 /* pic14_getDataSize - get the operand data size                   */
1807 /*-----------------------------------------------------------------*/
1808 int pic14_getDataSize(operand *op)
1809 {
1810         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1811         
1812         
1813         return AOP_SIZE(op);
1814         
1815         // tsd- in the pic port, the genptr size is 1, so this code here
1816         // fails. ( in the 8051 port, the size was 4).
1817 #if 0
1818         int size;
1819         size = AOP_SIZE(op);
1820         if (size == GPTRSIZE)
1821         {
1822                 sym_link *type = operandType(op);
1823                 if (IS_GENPTR(type))
1824                 {
1825                         /* generic pointer; arithmetic operations
1826                         * should ignore the high byte (pointer type).
1827                         */
1828                         size--;
1829                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1830                 }
1831         }
1832         return size;
1833 #endif
1834 }
1835
1836 /*-----------------------------------------------------------------*/
1837 /* pic14_outAcc - output Acc                                       */
1838 /*-----------------------------------------------------------------*/
1839 void pic14_outAcc(operand *result)
1840 {
1841         int size,offset;
1842         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1843         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1844         
1845         
1846         size = pic14_getDataSize(result);
1847         if(size){
1848                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1849                 size--;
1850                 offset = 1;
1851                 /* unsigned or positive */
1852                 while(size--)
1853                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1854         }
1855         
1856 }
1857
1858 /*-----------------------------------------------------------------*/
1859 /* pic14_outBitC - output a bit C                                  */
1860 /*-----------------------------------------------------------------*/
1861 void pic14_outBitC(operand *result)
1862 {
1863         
1864         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1865         /* if the result is bit */
1866         if (AOP_TYPE(result) == AOP_CRY) 
1867                 aopPut(AOP(result),"c",0);
1868         else {
1869                 pic14_emitcode("clr","a  ; %d", __LINE__);
1870                 pic14_emitcode("rlc","a");
1871                 pic14_outAcc(result);
1872         }
1873 }
1874
1875 /*-----------------------------------------------------------------*/
1876 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1877 /*-----------------------------------------------------------------*/
1878 void pic14_toBoolean(operand *oper)
1879 {
1880         int size = AOP_SIZE(oper) - 1;
1881         int offset = 1;
1882         
1883         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1884         
1885         if ( AOP_TYPE(oper) != AOP_ACC) {
1886                 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1887         }
1888         while (size--) {
1889                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1890         }
1891 }
1892
1893
1894 /*-----------------------------------------------------------------*/
1895 /* genNot - generate code for ! operation                          */
1896 /*-----------------------------------------------------------------*/
1897 static void genNot (iCode *ic)
1898 {
1899         symbol *tlbl;
1900         int size;
1901
1902         FENTRY;
1903         
1904         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1905         /* assign asmOps to operand & result */
1906         aopOp (IC_LEFT(ic),ic,FALSE);
1907         aopOp (IC_RESULT(ic),ic,TRUE);
1908         
1909         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1910         /* if in bit space then a special case */
1911         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1912                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1913                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1914                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1915                 } else {
1916                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1917                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1918                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1919                 }
1920                 goto release;
1921         }
1922         
1923         size = AOP_SIZE(IC_LEFT(ic));
1924         if(size == 1) {
1925                 emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1926                 emitpcode(POC_ANDLW,popGetLit(1));
1927                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1928                 goto release;
1929         }
1930         pic14_toBoolean(IC_LEFT(ic));
1931         
1932         tlbl = newiTempLabel(NULL);
1933         pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1934         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1935         pic14_outBitC(IC_RESULT(ic));
1936         
1937 release:        
1938         /* release the aops */
1939         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1940         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1941 }
1942
1943
1944 /*-----------------------------------------------------------------*/
1945 /* genCpl - generate code for complement                                                   */
1946 /*-----------------------------------------------------------------*/
1947 static void genCpl (iCode *ic)
1948 {
1949         operand *left, *result;
1950         int size, offset=0;  
1951         
1952         FENTRY;
1953         
1954         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1955         aopOp((left = IC_LEFT(ic)),ic,FALSE);
1956         aopOp((result=IC_RESULT(ic)),ic,TRUE);
1957         
1958         /* if both are in bit space then 
1959         a special case */
1960         if (AOP_TYPE(result) == AOP_CRY &&
1961                 AOP_TYPE(left) == AOP_CRY ) { 
1962                 
1963                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1964                 pic14_emitcode("cpl","c"); 
1965                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1966                 goto release; 
1967         } 
1968         
1969         size = AOP_SIZE(result);
1970         while (size--) {
1971                 
1972                 if(AOP_TYPE(left) == AOP_ACC) 
1973                         emitpcode(POC_XORLW, popGetLit(0xff));
1974                 else
1975                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
1976                 
1977                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1978                 offset++;
1979         }
1980         
1981         
1982 release:
1983         /* release the aops */
1984         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1985         freeAsmop(result,NULL,ic,TRUE);
1986 }
1987
1988 /*-----------------------------------------------------------------*/
1989 /* genUminusFloat - unary minus for floating points                        */
1990 /*-----------------------------------------------------------------*/
1991 static void genUminusFloat(operand *op,operand *result)
1992 {
1993         int size ,offset =0 ;
1994         char *l;
1995         
1996         FENTRY;
1997
1998         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1999         /* for this we just need to flip the 
2000         first it then copy the rest in place */
2001         size = AOP_SIZE(op) - 1;
2002         l = aopGet(AOP(op),3,FALSE,FALSE);
2003         
2004         MOVA(l);          
2005         
2006         pic14_emitcode("cpl","acc.7");
2007         aopPut(AOP(result),"a",3);      
2008         
2009         while(size--) {
2010                 aopPut(AOP(result),
2011                         aopGet(AOP(op),offset,FALSE,FALSE),
2012                         offset);
2013                 offset++;
2014         }                
2015 }
2016
2017 /*-----------------------------------------------------------------*/
2018 /* genUminus - unary minus code generation                                                 */
2019 /*-----------------------------------------------------------------*/
2020 static void genUminus (iCode *ic)
2021 {
2022         int size, i;
2023         sym_link *optype, *rtype;
2024         
2025         FENTRY;
2026         
2027         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2028         /* assign asmops */
2029         aopOp(IC_LEFT(ic),ic,FALSE);
2030         aopOp(IC_RESULT(ic),ic,TRUE);
2031         
2032         /* if both in bit space then special
2033         case */
2034         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2035                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2036                 
2037                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2038                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2039                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2040                 
2041                 goto release; 
2042         } 
2043         
2044         optype = operandType(IC_LEFT(ic));
2045         rtype = operandType(IC_RESULT(ic));
2046         
2047         /* if float then do float stuff */
2048         if (IS_FLOAT(optype)) {
2049                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2050                 goto release;
2051         }
2052         
2053         /* otherwise subtract from zero by taking the 2's complement */
2054         size = AOP_SIZE(IC_LEFT(ic));
2055         
2056         for(i=0; i<size; i++) {
2057                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2058                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2059                 else {
2060                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2061                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2062                 }
2063         }
2064         
2065         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2066         for(i=1; i<size; i++) {
2067                 emitSKPNZ;
2068                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2069         }
2070         
2071 release:
2072         /* release the aops */
2073         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2074         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2075 }
2076
2077 /*-----------------------------------------------------------------*/
2078 /* saveRegisters - will look for a call and save the registers     */
2079 /*-----------------------------------------------------------------*/
2080 static void saveRegisters(iCode *lic) 
2081 {
2082         int i;
2083         iCode *ic;
2084         bitVect *rsave;
2085         sym_link *dtype;
2086         
2087         FENTRY;
2088
2089         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2090         /* look for call */
2091         for (ic = lic ; ic ; ic = ic->next) 
2092                 if (ic->op == CALL || ic->op == PCALL)
2093                         break;
2094                 
2095                 if (!ic) {
2096                         fprintf(stderr,"found parameter push with no function call\n");
2097                         return ;
2098                 }
2099                 
2100                 /* if the registers have been saved already then
2101                 do nothing */
2102                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2103                         return ;
2104                 
2105                         /* find the registers in use at this time 
2106                 and push them away to safety */
2107                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2108                         ic->rUsed);
2109                 
2110                 ic->regsSaved = 1;
2111                 if (options.useXstack) {
2112                         if (bitVectBitValue(rsave,R0_IDX))
2113                                 pic14_emitcode("mov","b,r0");
2114                         pic14_emitcode("mov","r0,%s",spname);
2115                         for (i = 0 ; i < pic14_nRegs ; i++) {
2116                                 if (bitVectBitValue(rsave,i)) {
2117                                         if (i == R0_IDX)
2118                                                 pic14_emitcode("mov","a,b");
2119                                         else
2120                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2121                                         pic14_emitcode("movx","@r0,a");
2122                                         pic14_emitcode("inc","r0");
2123                                 }
2124                         }
2125                         pic14_emitcode("mov","%s,r0",spname);
2126                         if (bitVectBitValue(rsave,R0_IDX))
2127                                 pic14_emitcode("mov","r0,b");     
2128                 }// else
2129                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2130                 //        if (bitVectBitValue(rsave,i))
2131                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2132                 //}
2133                 
2134                 dtype = operandType(IC_LEFT(ic));
2135                 if (currFunc && dtype && 
2136                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2137                         IFFUNC_ISISR(currFunc->type) &&
2138                         !ic->bankSaved) 
2139                         
2140                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2141                 
2142 }
2143 /*-----------------------------------------------------------------*/
2144 /* unsaveRegisters - pop the pushed registers                                      */
2145 /*-----------------------------------------------------------------*/
2146 static void unsaveRegisters (iCode *ic)
2147 {
2148         int i;
2149         bitVect *rsave;
2150         
2151         FENTRY;
2152
2153         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2154         /* find the registers in use at this time 
2155         and push them away to safety */
2156         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2157                 ic->rUsed);
2158         
2159         if (options.useXstack) {
2160                 pic14_emitcode("mov","r0,%s",spname); 
2161                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2162                         if (bitVectBitValue(rsave,i)) {
2163                                 pic14_emitcode("dec","r0");
2164                                 pic14_emitcode("movx","a,@r0");
2165                                 if (i == R0_IDX)
2166                                         pic14_emitcode("mov","b,a");
2167                                 else
2168                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2169                         }       
2170                         
2171                 }
2172                 pic14_emitcode("mov","%s,r0",spname);
2173                 if (bitVectBitValue(rsave,R0_IDX))
2174                         pic14_emitcode("mov","r0,b");
2175         } //else
2176         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2177         //      if (bitVectBitValue(rsave,i))
2178         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2179         //}
2180         
2181 }  
2182
2183
2184 /*-----------------------------------------------------------------*/
2185 /* pushSide -                            */
2186 /*-----------------------------------------------------------------*/
2187 static void pushSide(operand * oper, int size)
2188 {
2189 #if 0
2190         int offset = 0;
2191         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2192         while (size--) {
2193                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2194                 if (AOP_TYPE(oper) != AOP_REG &&
2195                         AOP_TYPE(oper) != AOP_DIR &&
2196                         strcmp(l,"a") ) {
2197                         pic14_emitcode("mov","a,%s",l);
2198                         pic14_emitcode("push","acc");
2199                 } else
2200                         pic14_emitcode("push","%s",l);
2201         }
2202 #endif
2203 }
2204
2205 /*-----------------------------------------------------------------*/
2206 /* assignResultValue -                           */
2207 /*-----------------------------------------------------------------*/
2208 static void assignResultValue(operand * oper)
2209 {
2210         int size = AOP_SIZE(oper);
2211         
2212         FENTRY;
2213
2214         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2215         
2216         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2217         
2218         while (size--) {
2219                 if (GpsuedoStkPtr++)
2220                         emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2221                 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2222         }
2223 }
2224
2225
2226 /*-----------------------------------------------------------------*/
2227 /* genIpush - genrate code for pushing this gets a little complex  */
2228 /*-----------------------------------------------------------------*/
2229 static void genIpush (iCode *ic)
2230 {
2231         FENTRY;
2232         
2233         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2234 #if 0
2235         int size, offset = 0 ;
2236         char *l;
2237         
2238         
2239         /* if this is not a parm push : ie. it is spill push 
2240         and spill push is always done on the local stack */
2241         if (!ic->parmPush) {
2242                 
2243                 /* and the item is spilt then do nothing */
2244                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2245                         return ;
2246                 
2247                 aopOp(IC_LEFT(ic),ic,FALSE);
2248                 size = AOP_SIZE(IC_LEFT(ic));
2249                 /* push it on the stack */
2250                 while(size--) {
2251                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2252                         if (*l == '#') {
2253                                 MOVA(l);
2254                                 l = "acc";
2255                         }
2256                         pic14_emitcode("push","%s",l);
2257                 }
2258                 return ;                
2259         }
2260         
2261         /* this is a paramter push: in this case we call
2262         the routine to find the call and save those
2263         registers that need to be saved */   
2264         saveRegisters(ic);
2265         
2266         /* then do the push */
2267         aopOp(IC_LEFT(ic),ic,FALSE);
2268         
2269         
2270         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2271         size = AOP_SIZE(IC_LEFT(ic));
2272         
2273         while (size--) {
2274                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2275                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2276                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2277                         strcmp(l,"a") ) {
2278                         pic14_emitcode("mov","a,%s",l);
2279                         pic14_emitcode("push","acc");
2280                 } else
2281                         pic14_emitcode("push","%s",l);
2282         }         
2283         
2284         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2285 #endif
2286 }
2287
2288 /*-----------------------------------------------------------------*/
2289 /* genIpop - recover the registers: can happen only for spilling   */
2290 /*-----------------------------------------------------------------*/
2291 static void genIpop (iCode *ic)
2292 {
2293         FENTRY;
2294
2295         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2296 #if 0
2297         int size,offset ;
2298         
2299         
2300         /* if the temp was not pushed then */
2301         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2302                 return ;
2303         
2304         aopOp(IC_LEFT(ic),ic,FALSE);
2305         size = AOP_SIZE(IC_LEFT(ic));
2306         offset = (size-1);
2307         while (size--) 
2308                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2309                 FALSE,TRUE));
2310         
2311         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2312 #endif
2313 }
2314
2315 /*-----------------------------------------------------------------*/
2316 /* unsaverbank - restores the resgister bank from stack                    */
2317 /*-----------------------------------------------------------------*/
2318 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2319 {
2320         FENTRY;
2321
2322         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2323 #if 0
2324         int i;
2325         asmop *aop ;
2326         regs *r = NULL;
2327         
2328         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2329         if (popPsw) {
2330                 if (options.useXstack) {
2331                         aop = newAsmop(0);
2332                         r = getFreePtr(ic,&aop,FALSE);
2333                         
2334                         
2335                         pic14_emitcode("mov","%s,_spx",r->name);
2336                         pic14_emitcode("movx","a,@%s",r->name);
2337                         pic14_emitcode("mov","psw,a");
2338                         pic14_emitcode("dec","%s",r->name);
2339                         
2340                 }else
2341                         pic14_emitcode ("pop","psw");
2342         }
2343         
2344         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2345                 if (options.useXstack) {           
2346                         pic14_emitcode("movx","a,@%s",r->name);
2347                         //pic14_emitcode("mov","(%s+%d),a",
2348                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2349                         pic14_emitcode("dec","%s",r->name);
2350                         
2351                 } else 
2352                         pic14_emitcode("pop",""); //"(%s+%d)",
2353                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2354         }
2355         
2356         if (options.useXstack) {
2357                 
2358                 pic14_emitcode("mov","_spx,%s",r->name);
2359                 freeAsmop(NULL,aop,ic,TRUE);
2360                 
2361         }
2362 #endif 
2363 }
2364
2365 /*-----------------------------------------------------------------*/
2366 /* saverbank - saves an entire register bank on the stack                  */
2367 /*-----------------------------------------------------------------*/
2368 static void saverbank (int bank, iCode *ic, bool pushPsw)
2369 {
2370         FENTRY;
2371
2372         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2373 #if 0
2374         int i;
2375         asmop *aop ;
2376         regs *r = NULL;
2377         
2378         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2379         if (options.useXstack) {
2380                 
2381                 aop = newAsmop(0);
2382                 r = getFreePtr(ic,&aop,FALSE);  
2383                 pic14_emitcode("mov","%s,_spx",r->name);
2384                 
2385         }
2386         
2387         for (i = 0 ; i < pic14_nRegs ;i++) {
2388                 if (options.useXstack) {
2389                         pic14_emitcode("inc","%s",r->name);
2390                         //pic14_emitcode("mov","a,(%s+%d)",
2391                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2392                         pic14_emitcode("movx","@%s,a",r->name);                 
2393                 } else 
2394                         pic14_emitcode("push","");// "(%s+%d)",
2395                 //regspic14[i].base,8*bank+regspic14[i].offset);
2396         }
2397         
2398         if (pushPsw) {
2399                 if (options.useXstack) {
2400                         pic14_emitcode("mov","a,psw");
2401                         pic14_emitcode("movx","@%s,a",r->name); 
2402                         pic14_emitcode("inc","%s",r->name);
2403                         pic14_emitcode("mov","_spx,%s",r->name);                 
2404                         freeAsmop (NULL,aop,ic,TRUE);
2405                         
2406                 } else
2407                         pic14_emitcode("push","psw");
2408                 
2409                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2410         }
2411         ic->bankSaved = 1;
2412 #endif
2413 }
2414
2415 /*-----------------------------------------------------------------*/
2416 /* genCall - generates a call statement                                                    */
2417 /*-----------------------------------------------------------------*/
2418 static void genCall (iCode *ic)
2419 {
2420         sym_link *dtype;         
2421         symbol *sym;
2422         unsigned char *name;
2423         int isExtern;
2424         
2425         FENTRY;
2426
2427         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2428         
2429         /* if caller saves & we have not saved then */
2430         if (!ic->regsSaved)
2431                 saveRegisters(ic);
2432         
2433                 /* if we are calling a function that is not using
2434                 the same register bank then we need to save the
2435         destination registers on the stack */
2436         dtype = operandType(IC_LEFT(ic));
2437         if (currFunc && dtype && 
2438                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2439                 IFFUNC_ISISR(currFunc->type) &&
2440                 !ic->bankSaved) 
2441                 
2442                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2443         
2444         /* if send set is not empty the assign */
2445         if (_G.sendSet) {
2446                 iCode *sic;
2447                 /* For the Pic port, there is no data stack.
2448                 * So parameters passed to functions are stored
2449                 * in registers. (The pCode optimizer will get
2450                 * rid of most of these :).
2451                 */
2452                 int psuedoStkPtr=-1;
2453                 int firstTimeThruLoop = 1;
2454                 
2455                 _G.sendSet = reverseSet(_G.sendSet);
2456                 
2457                 /* First figure how many parameters are getting passed */
2458                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2459                 sic = setNextItem(_G.sendSet)) {
2460                         
2461                         aopOp(IC_LEFT(sic),sic,FALSE);
2462                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2463                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2464                 }
2465                 
2466                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2467                 sic = setNextItem(_G.sendSet)) {
2468                         int size, offset = 0;
2469                         
2470                         aopOp(IC_LEFT(sic),sic,FALSE);
2471                         size = AOP_SIZE(IC_LEFT(sic));
2472                         
2473                         while (size--) {
2474                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2475                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2476                                 
2477                                 if(!firstTimeThruLoop) {
2478                                         /* If this is not the first time we've been through the loop
2479                                         * then we need to save the parameter in a temporary
2480                                         * register. The last byte of the last parameter is
2481                                         * passed in W. */
2482                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2483                                         
2484                                 }
2485                                 firstTimeThruLoop=0;
2486                                 
2487                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2488                                 offset++;
2489                         }
2490                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2491                 }
2492                 _G.sendSet = NULL;
2493         }
2494         /* make the call */
2495         sym = OP_SYMBOL(IC_LEFT(ic));
2496         name = sym->rname[0] ? sym->rname : sym->name;
2497         isExtern = IS_EXTERN(sym->etype);
2498         if (isExtern) {
2499                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2500         }
2501         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2502         if (isExtern) {
2503                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2504         }
2505         GpsuedoStkPtr=0;
2506         /* if we need assign a result value */
2507         if ((IS_ITEMP(IC_RESULT(ic)) && 
2508                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2509                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2510                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2511                 
2512                 _G.accInUse++;
2513                 aopOp(IC_RESULT(ic),ic,FALSE);
2514                 _G.accInUse--;
2515                 
2516                 assignResultValue(IC_RESULT(ic));
2517                 
2518                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2519                         AopType(AOP_TYPE(IC_RESULT(ic))));
2520                 
2521                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2522         }
2523         
2524         /* adjust the stack for parameters if 
2525         required */
2526         if (ic->parmBytes) {
2527                 int i;
2528                 if (ic->parmBytes > 3) {
2529                         pic14_emitcode("mov","a,%s",spname);
2530                         pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2531                         pic14_emitcode("mov","%s,a",spname);
2532                 } else 
2533                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2534                                 pic14_emitcode("dec","%s",spname);
2535                         
2536         }
2537         
2538         /* if register bank was saved then pop them */
2539         if (ic->bankSaved)
2540                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2541         
2542         /* if we hade saved some registers then unsave them */
2543         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2544                 unsaveRegisters (ic);
2545         
2546         
2547 }
2548
2549 /*-----------------------------------------------------------------*/
2550 /* genPcall - generates a call by pointer statement                        */
2551 /*-----------------------------------------------------------------*/
2552 static void genPcall (iCode *ic)
2553 {
2554         sym_link *dtype;
2555         symbol *albl = newiTempLabel(NULL);
2556         symbol *blbl = newiTempLabel(NULL);
2557         PIC_OPCODE poc;
2558         pCodeOp *pcop;
2559         operand *left;
2560         
2561         FENTRY;
2562
2563         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2564         /* if caller saves & we have not saved then */
2565         if (!ic->regsSaved)
2566                 saveRegisters(ic);
2567         
2568                 /* if we are calling a function that is not using
2569                 the same register bank then we need to save the
2570         destination registers on the stack */
2571         dtype = operandType(IC_LEFT(ic));
2572         if (currFunc && dtype && 
2573                 IFFUNC_ISISR(currFunc->type) &&
2574                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2575                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2576         
2577         left = IC_LEFT(ic);
2578         aopOp(left,ic,FALSE);
2579         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2580         
2581         pushSide(IC_LEFT(ic), FPTRSIZE);
2582         
2583         /* if send set is not empty, assign parameters */
2584         if (_G.sendSet) {
2585                 
2586                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2587                 /* no way to pass args - W always gets used to make the call */
2588         }
2589         /* first idea - factor out a common helper function and call it.
2590         But don't know how to get it generated only once in its own block
2591         
2592         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2593                 char *rname;
2594                 char *buffer;
2595                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2596                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2597                 buffer = Safe_calloc(1,strlen(rname)+16);
2598                 sprintf(buffer, "%s_goto_helper", rname);
2599                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2600                 free(buffer);
2601         }
2602         */
2603         emitpcode(POC_CALL,popGetLabel(albl->key));
2604         pcop = popGetLabel(blbl->key);
2605         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2606         emitpcode(POC_GOTO,pcop);
2607         emitpLabel(albl->key);
2608         
2609         poc = ( aop_isLitLike (AOP(left)) ? POC_MOVLW : POC_MOVFW );
2610         
2611         emitpcode(poc,popGetAddr(AOP(left),1,0));
2612         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2613         emitpcode(poc,popGetAddr(AOP(left),0,0));
2614         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2615         
2616         emitpLabel(blbl->key);
2617         
2618         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2619         
2620         /* if we need to assign a result value */
2621         if ((IS_ITEMP(IC_RESULT(ic)) &&
2622                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2623                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2624                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2625                 
2626                 _G.accInUse++;
2627                 aopOp(IC_RESULT(ic),ic,FALSE);
2628                 _G.accInUse--;
2629                 
2630                 assignResultValue(IC_RESULT(ic));
2631                 
2632                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2633         }
2634         
2635         /* if register bank was saved then unsave them */
2636         if (currFunc && dtype && 
2637                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2638                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2639         
2640                 /* if we hade saved some registers then
2641         unsave them */
2642         if (ic->regsSaved)
2643                 unsaveRegisters (ic);
2644         
2645 }
2646
2647 /*-----------------------------------------------------------------*/
2648 /* resultRemat - result  is rematerializable                                       */
2649 /*-----------------------------------------------------------------*/
2650 static int resultRemat (iCode *ic)
2651 {
2652         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2653         FENTRY;
2654
2655         if (SKIP_IC(ic) || ic->op == IFX)
2656                 return 0;
2657         
2658         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2659                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2660                 if (sym->remat && !POINTER_SET(ic)) 
2661                         return 1;
2662         }
2663         
2664         return 0;
2665 }
2666
2667 #if defined(__BORLANDC__) || defined(_MSC_VER)
2668 #define STRCASECMP stricmp
2669 #else
2670 #define STRCASECMP strcasecmp
2671 #endif
2672
2673 #if 0
2674 /*-----------------------------------------------------------------*/
2675 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2676 /*-----------------------------------------------------------------*/
2677 static bool inExcludeList(char *s)
2678 {
2679         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2680         int i =0;
2681         
2682         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2683         if (options.excludeRegs[i] &&
2684                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2685                 return FALSE ;
2686         
2687         for ( i = 0 ; options.excludeRegs[i]; i++) {
2688                 if (options.excludeRegs[i] &&
2689                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2690                         return TRUE;
2691         }
2692         return FALSE ;
2693 }
2694 #endif
2695
2696 /*-----------------------------------------------------------------*/
2697 /* genFunction - generated code for function entry                                 */
2698 /*-----------------------------------------------------------------*/
2699 static void genFunction (iCode *ic)
2700 {
2701         symbol *sym;
2702         sym_link *ftype;
2703         
2704         FENTRY;
2705
2706         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2707         
2708         labelOffset += (max_key+4);
2709         max_key=0;
2710         GpsuedoStkPtr=0;
2711         _G.nRegsSaved = 0;
2712         /* create the function header */
2713         pic14_emitcode(";","-----------------------------------------");
2714         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2715         pic14_emitcode(";","-----------------------------------------");
2716         
2717         pic14_emitcode("","%s:",sym->rname);
2718         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2719         
2720         ftype = operandType(IC_LEFT(ic));
2721         
2722         /* if critical function then turn interrupts off */
2723         if (IFFUNC_ISCRITICAL(ftype))
2724                 pic14_emitcode("clr","ea");
2725         
2726                 /* here we need to generate the equates for the
2727         register bank if required */
2728 #if 0
2729         if (FUNC_REGBANK(ftype) != rbank) {
2730                 int i ;
2731                 
2732                 rbank = FUNC_REGBANK(ftype);
2733                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2734                         if (strcmp(regspic14[i].base,"0") == 0)
2735                                 pic14_emitcode("","%s = 0x%02x",
2736                                 regspic14[i].dname,
2737                                 8*rbank+regspic14[i].offset);
2738                         else
2739                                 pic14_emitcode ("","%s = %s + 0x%02x",
2740                                 regspic14[i].dname,
2741                                 regspic14[i].base,
2742                                 8*rbank+regspic14[i].offset);
2743                 }
2744         }
2745 #endif
2746         
2747         /* if this is an interrupt service routine */
2748         if (IFFUNC_ISISR(sym->type)) {
2749         /*  already done in pic14createInterruptVect() - delete me
2750         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2751         emitpcodeNULLop(POC_NOP);
2752         emitpcodeNULLop(POC_NOP);
2753         emitpcodeNULLop(POC_NOP);
2754                 */
2755                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2756                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2757                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2758                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2759                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2760                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2761                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2762                 
2763                 pBlockConvert2ISR(pb);
2764 #if 0  
2765                 if (!inExcludeList("acc"))              
2766                         pic14_emitcode ("push","acc");  
2767                 if (!inExcludeList("b"))
2768                         pic14_emitcode ("push","b");
2769                 if (!inExcludeList("dpl"))
2770                         pic14_emitcode ("push","dpl");
2771                 if (!inExcludeList("dph"))
2772                         pic14_emitcode ("push","dph");
2773                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2774                 {
2775                         pic14_emitcode ("push", "dpx");
2776                         /* Make sure we're using standard DPTR */
2777                         pic14_emitcode ("push", "dps");
2778                         pic14_emitcode ("mov", "dps, #0x00");
2779                         if (options.stack10bit)
2780                         { 
2781                                 /* This ISR could conceivably use DPTR2. Better save it. */
2782                                 pic14_emitcode ("push", "dpl1");
2783                                 pic14_emitcode ("push", "dph1");
2784                                 pic14_emitcode ("push", "dpx1");
2785                         }
2786                 }
2787                 /* if this isr has no bank i.e. is going to
2788                 run with bank 0 , then we need to save more
2789                 registers :-) */
2790                 if (!FUNC_REGBANK(sym->type)) {
2791                         
2792                 /* if this function does not call any other
2793                 function then we can be economical and
2794                         save only those registers that are used */
2795                         if (! IFFUNC_HASFCALL(sym->type)) {
2796                                 int i;
2797                                 
2798                                 /* if any registers used */
2799                                 if (sym->regsUsed) {
2800                                         /* save the registers used */
2801                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2802                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2803                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2804                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2805                                         }
2806                                 }
2807                                 
2808                         } else {
2809                         /* this function has    a function call cannot
2810                         determines register usage so we will have the
2811                                 entire bank */
2812                                 saverbank(0,ic,FALSE);
2813                         }       
2814                 }
2815 #endif
2816         } else {
2817         /* if callee-save to be used for this function
2818                 then save the registers being used in this function */
2819                 if (IFFUNC_CALLEESAVES(sym->type)) {
2820                         int i;
2821                         
2822                         /* if any registers used */
2823                         if (sym->regsUsed) {
2824                                 /* save the registers used */
2825                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2826                                         if (bitVectBitValue(sym->regsUsed,i) ||
2827                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2828                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2829                                                 _G.nRegsSaved++;
2830                                         }
2831                                 }
2832                         }
2833                 }
2834         }
2835         
2836         /* set the register bank to the desired value */
2837         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2838                 pic14_emitcode("push","psw");
2839                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
2840         }
2841         
2842         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2843                 
2844                 if (options.useXstack) {
2845                         pic14_emitcode("mov","r0,%s",spname);
2846                         pic14_emitcode("mov","a,_bp");
2847                         pic14_emitcode("movx","@r0,a");
2848                         pic14_emitcode("inc","%s",spname);
2849                 }
2850                 else
2851                 {
2852                         /* set up the stack */
2853                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
2854                 }
2855                 pic14_emitcode ("mov","_bp,%s",spname);
2856         }
2857         
2858         /* adjust the stack for the function */
2859         if (sym->stack) {
2860                 
2861                 int i = sym->stack;
2862                 if (i > 256 ) 
2863                         werror(W_STACK_OVERFLOW,sym->name);
2864                 
2865                 if (i > 3 && sym->recvSize < 4) {                
2866                         
2867                         pic14_emitcode ("mov","a,sp");
2868                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2869                         pic14_emitcode ("mov","sp,a");
2870                         
2871                 }
2872                 else
2873                         while(i--)
2874                                 pic14_emitcode("inc","sp");
2875         }
2876         
2877         if (sym->xstack) {
2878                 
2879                 pic14_emitcode ("mov","a,_spx");
2880                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2881                 pic14_emitcode ("mov","_spx,a");
2882         }
2883         
2884 }
2885
2886 /*-----------------------------------------------------------------*/
2887 /* genEndFunction - generates epilogue for functions                       */
2888 /*-----------------------------------------------------------------*/
2889 static void genEndFunction (iCode *ic)
2890 {
2891         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2892         
2893         FENTRY;
2894
2895         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2896         
2897         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2898         {
2899                 pic14_emitcode ("mov","%s,_bp",spname);
2900         }
2901         
2902         /* if use external stack but some variables were
2903         added to the local stack then decrement the
2904         local stack */
2905         if (options.useXstack && sym->stack) {    
2906                 pic14_emitcode("mov","a,sp");
2907                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2908                 pic14_emitcode("mov","sp,a");
2909         }
2910         
2911         
2912         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2913                 if (options.useXstack) {
2914                         pic14_emitcode("mov","r0,%s",spname);
2915                         pic14_emitcode("movx","a,@r0");
2916                         pic14_emitcode("mov","_bp,a");
2917                         pic14_emitcode("dec","%s",spname);
2918                 }
2919                 else
2920                 {
2921                         pic14_emitcode ("pop","_bp");
2922                 }
2923         }
2924         
2925         /* restore the register bank    */        
2926         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2927                 pic14_emitcode ("pop","psw");
2928         
2929         if (IFFUNC_ISISR(sym->type)) {
2930                 
2931                 /* now we need to restore the registers */
2932                 /* if this isr has no bank i.e. is going to
2933                 run with bank 0 , then we need to save more
2934 registers :-) */
2935                 if (!FUNC_REGBANK(sym->type)) {
2936                         
2937                 /* if this function does not call any other
2938                 function then we can be economical and
2939                         save only those registers that are used */
2940                         if (! IFFUNC_HASFCALL(sym->type)) {
2941                                 int i;
2942                                 
2943                                 /* if any registers used */
2944                                 if (sym->regsUsed) {
2945                                         /* save the registers used */
2946                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2947                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2948                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2949                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2950                                         }
2951                                 }
2952                                 
2953                         } else {
2954                         /* this function has    a function call cannot
2955                         determines register usage so we will have the
2956                                 entire bank */
2957                                 unsaverbank(0,ic,FALSE);
2958                         }       
2959                 }
2960 #if 0
2961                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2962                 {
2963                         if (options.stack10bit)
2964                         {
2965                                 pic14_emitcode ("pop", "dpx1");
2966                                 pic14_emitcode ("pop", "dph1");
2967                                 pic14_emitcode ("pop", "dpl1");
2968                         } 
2969                         pic14_emitcode ("pop", "dps");
2970                         pic14_emitcode ("pop", "dpx");
2971                 }
2972                 if (!inExcludeList("dph"))
2973                         pic14_emitcode ("pop","dph");
2974                 if (!inExcludeList("dpl"))
2975                         pic14_emitcode ("pop","dpl");
2976                 if (!inExcludeList("b"))
2977                         pic14_emitcode ("pop","b");
2978                 if (!inExcludeList("acc"))
2979                         pic14_emitcode ("pop","acc");
2980                 
2981                 if (IFFUNC_ISCRITICAL(sym->type))
2982                         pic14_emitcode("setb","ea");
2983 #endif
2984                 
2985                 /* if debug then send end of function */
2986                 /*      if (options.debug && currFunc) { */
2987                 if (currFunc) {
2988                         debugFile->writeEndFunction (currFunc, ic, 1);
2989                 }
2990                 
2991                 pic14_emitcode ("reti","");
2992                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2993                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2994                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2995                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
2996                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
2997                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
2998                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
2999                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3000                 emitpcodeNULLop(POC_RETFIE);
3001         }
3002         else {
3003                 if (IFFUNC_ISCRITICAL(sym->type))
3004                         pic14_emitcode("setb","ea");
3005                 
3006                 if (IFFUNC_CALLEESAVES(sym->type)) {
3007                         int i;
3008                         
3009                         /* if any registers used */
3010                         if (sym->regsUsed) {
3011                                 /* save the registers used */
3012                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3013                                         if (bitVectBitValue(sym->regsUsed,i) ||
3014                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3015                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3016                                 }
3017                         }
3018                         
3019                 }
3020                 
3021                 /* if debug then send end of function */
3022                 if (currFunc) {
3023                         debugFile->writeEndFunction (currFunc, ic, 1);
3024                 }
3025                 
3026                 pic14_emitcode ("return","");
3027                 emitpcodeNULLop(POC_RETURN);
3028                 
3029                 /* Mark the end of a function */
3030                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3031         }
3032         
3033 }
3034
3035 /*-----------------------------------------------------------------*/
3036 /* genRet - generate code for return statement                                     */
3037 /*-----------------------------------------------------------------*/
3038 static void genRet (iCode *ic)
3039 {
3040         int size,offset = 0 , pushed = 0;
3041         
3042         FENTRY;
3043
3044         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3045         /* if we have no return value then
3046         just generate the "ret" */
3047         if (!IC_LEFT(ic)) 
3048                 goto jumpret;           
3049         
3050                 /* we have something to return then
3051         move the return value into place */
3052         aopOp(IC_LEFT(ic),ic,FALSE);
3053         size = AOP_SIZE(IC_LEFT(ic));
3054         
3055         while (size--) {
3056                 char *l ;
3057                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3058                         /* #NOCHANGE */
3059                         l = aopGet(AOP(IC_LEFT(ic)),offset++,
3060                                 FALSE,TRUE);
3061                         pic14_emitcode("push","%s",l);
3062                         pushed++;
3063                 } else {
3064                         l = aopGet(AOP(IC_LEFT(ic)),offset,
3065                                 FALSE,FALSE);
3066                         if (strcmp(fReturn[offset],l)) {
3067                                 if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
3068                                         AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
3069                                         ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3070                                         ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3071                                         emitpcode(POC_MOVLW, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
3072                                 }else {
3073                                         emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3074                                 }
3075                                 if(size) {
3076                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
3077                                 }
3078                                 offset++;
3079                         }
3080                 }
3081         }
3082         
3083         if (pushed) {
3084                 while(pushed) {
3085                         pushed--;
3086                         if (strcmp(fReturn[pushed],"a"))
3087                                 pic14_emitcode("pop",fReturn[pushed]);
3088                         else
3089                                 pic14_emitcode("pop","acc");
3090                 }
3091         }
3092         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3093         
3094 jumpret:
3095         /* generate a jump to the return label
3096         if the next is not the return statement */
3097         if (!(ic->next && ic->next->op == LABEL &&
3098                 IC_LABEL(ic->next) == returnLabel)) {
3099                 
3100                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3101                 pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3102         }
3103         
3104 }
3105
3106 /*-----------------------------------------------------------------*/
3107 /* genLabel - generates a label                                                                    */
3108 /*-----------------------------------------------------------------*/
3109 static void genLabel (iCode *ic)
3110 {
3111         FENTRY;
3112
3113         /* special case never generate */
3114         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3115         if (IC_LABEL(ic) == entryLabel)
3116                 return ;
3117         
3118         emitpLabel(IC_LABEL(ic)->key);
3119         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3120 }
3121
3122 /*-----------------------------------------------------------------*/
3123 /* genGoto - generates a goto                                                                      */
3124 /*-----------------------------------------------------------------*/
3125 //tsd
3126 static void genGoto (iCode *ic)
3127 {
3128         FENTRY;
3129
3130         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3131         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3132 }
3133
3134
3135 /*-----------------------------------------------------------------*/
3136 /* genMultbits :- multiplication of bits                                                   */
3137 /*-----------------------------------------------------------------*/
3138 static void genMultbits (operand *left, 
3139                                                  operand *right, 
3140                                                  operand *result)
3141 {
3142         FENTRY;
3143         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3144         
3145         if(!pic14_sameRegs(AOP(result),AOP(right)))
3146                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3147         
3148         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3149         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3150         emitpcode(POC_BCF,  popGet(AOP(result),0));
3151         
3152 }
3153
3154
3155 /*-----------------------------------------------------------------*/
3156 /* genMultOneByte : 8 bit multiplication & division                        */
3157 /*-----------------------------------------------------------------*/
3158 static void genMultOneByte (operand *left,
3159                                                         operand *right,
3160                                                         operand *result)
3161 {
3162         sym_link *opetype = operandType(result);
3163         
3164         // symbol *lbl ;
3165         int size,offset;
3166         
3167         FENTRY;
3168         
3169         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3170         DEBUGpic14_AopType(__LINE__,left,right,result);
3171         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3172         
3173         /* (if two literals, the value is computed before) */
3174         /* if one literal, literal on the right */
3175         if (AOP_TYPE(left) == AOP_LIT){
3176                 operand *t = right;
3177                 right = left;
3178                 left = t;
3179         }
3180         
3181         size = AOP_SIZE(result);
3182         if(size == 1) {
3183                 
3184                 if (AOP_TYPE(right) == AOP_LIT){
3185                         pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3186                                 aopGet(AOP(right),0,FALSE,FALSE), 
3187                                 aopGet(AOP(left),0,FALSE,FALSE), 
3188                                 aopGet(AOP(result),0,FALSE,FALSE));
3189                         pic14_emitcode("call","genMultLit");
3190                 } else {
3191                         pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3192                                 aopGet(AOP(right),0,FALSE,FALSE), 
3193                                 aopGet(AOP(left),0,FALSE,FALSE), 
3194                                 aopGet(AOP(result),0,FALSE,FALSE));
3195                         pic14_emitcode("call","genMult8X8_8");
3196                         
3197                 }
3198                 genMult8X8_8 (left, right,result);
3199                 
3200                 
3201                 /* signed or unsigned */
3202                 //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3203                 //l = aopGet(AOP(left),0,FALSE,FALSE);
3204                 //MOVA(l);               
3205                 //pic14_emitcode("mul","ab");
3206                 /* if result size = 1, mul signed = mul unsigned */
3207                 //aopPut(AOP(result),"a",0);
3208                 
3209         } else {        // (size > 1)
3210                 
3211                 pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3212                         aopGet(AOP(right),0,FALSE,FALSE), 
3213                         aopGet(AOP(left),0,FALSE,FALSE), 
3214                         aopGet(AOP(result),0,FALSE,FALSE));
3215                 
3216                 if (SPEC_USIGN(opetype)){
3217                         pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3218                         genUMult8X8_16 (left, right, result, NULL);
3219                         
3220                         if (size > 2) {
3221                                 /* for filling the MSBs */
3222                                 emitpcode(POC_CLRF,  popGet(AOP(result),2));
3223                                 emitpcode(POC_CLRF,  popGet(AOP(result),3));
3224                         }
3225                 }
3226                 else{
3227                         pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3228                         
3229                         pic14_emitcode("mov","a,b");
3230                         
3231                         /* adjust the MSB if left or right neg */
3232                         
3233                         /* if one literal */
3234                         if (AOP_TYPE(right) == AOP_LIT){
3235                                 pic14_emitcode("multiply ","right is a lit");
3236                                 /* AND literal negative */
3237                                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3238                                         /* adjust MSB (c==0 after mul) */
3239                                         pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3240                                 }
3241                         }
3242                         else{
3243                                 genSMult8X8_16 (left, right, result, NULL);
3244                         }
3245                         
3246                         if(size > 2){
3247                                 pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3248                                 /* get the sign */
3249                                 pic14_emitcode("rlc","a");
3250                                 pic14_emitcode("subb","a,acc");
3251                         }
3252                 }
3253                 
3254                 size -= 2;
3255                 offset = 2;
3256                 if (size > 0)
3257                         while (size--)
3258                                 pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3259                         //aopPut(AOP(result),"a",offset++);
3260         }
3261 }
3262
3263 /*-----------------------------------------------------------------*/
3264 /* genMult - generates code for multiplication                                     */
3265 /*-----------------------------------------------------------------*/
3266 static void genMult (iCode *ic)
3267 {
3268         operand *left = IC_LEFT(ic);
3269         operand *right = IC_RIGHT(ic);
3270         operand *result= IC_RESULT(ic); 
3271         
3272         FENTRY;
3273
3274         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3275         /* assign the amsops */
3276         aopOp (left,ic,FALSE);
3277         aopOp (right,ic,FALSE);
3278         aopOp (result,ic,TRUE);
3279         
3280         DEBUGpic14_AopType(__LINE__,left,right,result);
3281         
3282         /* special cases first */
3283         /* both are bits */
3284         if (AOP_TYPE(left) == AOP_CRY &&
3285                 AOP_TYPE(right)== AOP_CRY) {
3286                 genMultbits(left,right,result);
3287                 goto release ;
3288         }
3289         
3290         /* if both are of size == 1 */
3291         if (AOP_SIZE(left) == 1 &&
3292                 AOP_SIZE(right) == 1 ) {
3293                 genMultOneByte(left,right,result);
3294                 goto release ;
3295         }
3296         
3297         pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3298         
3299         /* should have been converted to function call */
3300         //assert(0) ;
3301         
3302 release :
3303         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3304         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3305         freeAsmop(result,NULL,ic,TRUE); 
3306 }
3307
3308 /*-----------------------------------------------------------------*/
3309 /* genDivbits :- division of bits                                                                  */
3310 /*-----------------------------------------------------------------*/
3311 static void genDivbits (operand *left, 
3312                                                 operand *right, 
3313                                                 operand *result)
3314 {
3315         
3316         char *l;
3317         
3318         FENTRY;
3319
3320         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3321         /* the result must be bit */      
3322         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3323         l = aopGet(AOP(left),0,FALSE,FALSE);
3324         
3325         MOVA(l);          
3326         
3327         pic14_emitcode("div","ab");
3328         pic14_emitcode("rrc","a");
3329         aopPut(AOP(result),"c",0);
3330 }
3331
3332 /*-----------------------------------------------------------------*/
3333 /* genDivOneByte : 8 bit division                                                                  */
3334 /*-----------------------------------------------------------------*/
3335 static void genDivOneByte (operand *left,
3336                                                    operand *right,
3337                                                    operand *result)
3338 {
3339         sym_link *opetype = operandType(result);
3340         char *l ;
3341         symbol *lbl ;
3342         int size,offset;
3343         
3344         FENTRY;
3345         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3346         size = AOP_SIZE(result) - 1;
3347         offset = 1;
3348         /* signed or unsigned */
3349         if (SPEC_USIGN(opetype)) {
3350                 /* unsigned is easy */
3351                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3352                 l = aopGet(AOP(left),0,FALSE,FALSE);
3353                 MOVA(l);                
3354                 pic14_emitcode("div","ab");
3355                 aopPut(AOP(result),"a",0);
3356                 while (size--)
3357                         aopPut(AOP(result),zero,offset++);
3358                 return ;
3359         }
3360         
3361         /* signed is a little bit more difficult */
3362         
3363         /* save the signs of the operands */
3364         l = aopGet(AOP(left),0,FALSE,FALSE);      
3365         MOVA(l);          
3366         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3367         pic14_emitcode("push","acc"); /* save it on the stack */
3368         
3369         /* now sign adjust for both left & right */
3370         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3371         MOVA(l);                 
3372         lbl = newiTempLabel(NULL);
3373         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3374         pic14_emitcode("cpl","a");   
3375         pic14_emitcode("inc","a");
3376         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3377         pic14_emitcode("mov","b,a");
3378         
3379         /* sign adjust left side */
3380         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3381         MOVA(l);
3382         
3383         lbl = newiTempLabel(NULL);
3384         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3385         pic14_emitcode("cpl","a");
3386         pic14_emitcode("inc","a");
3387         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3388         
3389         /* now the division */
3390         pic14_emitcode("div","ab");
3391         /* we are interested in the lower order
3392         only */
3393         pic14_emitcode("mov","b,a");
3394         lbl = newiTempLabel(NULL);
3395         pic14_emitcode("pop","acc");     
3396         /* if there was an over flow we don't 
3397         adjust the sign of the result */
3398         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3399         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3400         CLRC;
3401         pic14_emitcode("clr","a");
3402         pic14_emitcode("subb","a,b");
3403         pic14_emitcode("mov","b,a");
3404         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3405         
3406         /* now we are done */
3407         aopPut(AOP(result),"b",0);
3408         if(size > 0){
3409                 pic14_emitcode("mov","c,b.7");
3410                 pic14_emitcode("subb","a,acc");   
3411         }
3412         while (size--)
3413                 aopPut(AOP(result),"a",offset++);
3414         
3415 }
3416
3417 /*-----------------------------------------------------------------*/
3418 /* genDiv - generates code for division                                                    */
3419 /*-----------------------------------------------------------------*/
3420 static void genDiv (iCode *ic)
3421 {
3422         operand *left = IC_LEFT(ic);
3423         operand *right = IC_RIGHT(ic);
3424         operand *result= IC_RESULT(ic); 
3425         
3426         FENTRY;
3427         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3428         /* assign the amsops */
3429         aopOp (left,ic,FALSE);
3430         aopOp (right,ic,FALSE);
3431         aopOp (result,ic,TRUE);
3432         
3433         /* special cases first */
3434         /* both are bits */
3435         if (AOP_TYPE(left) == AOP_CRY &&
3436                 AOP_TYPE(right)== AOP_CRY) {
3437                 genDivbits(left,right,result);
3438                 goto release ;
3439         }
3440         
3441         /* if both are of size == 1 */
3442         if (AOP_SIZE(left) == 1 &&
3443                 AOP_SIZE(right) == 1 ) {
3444                 genDivOneByte(left,right,result);
3445                 goto release ;
3446         }
3447         
3448         /* should have been converted to function call */
3449         assert(0);
3450 release :
3451         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3452         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3453         freeAsmop(result,NULL,ic,TRUE); 
3454 }
3455
3456 /*-----------------------------------------------------------------*/
3457 /* genModbits :- modulus of bits                                                                   */
3458 /*-----------------------------------------------------------------*/
3459 static void genModbits (operand *left, 
3460                                                 operand *right, 
3461                                                 operand *result)
3462 {
3463         
3464         char *l;
3465         
3466         FENTRY;
3467         /* the result must be bit */      
3468         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3469         l = aopGet(AOP(left),0,FALSE,FALSE);
3470         
3471         MOVA(l);
3472         
3473         pic14_emitcode("div","ab");
3474         pic14_emitcode("mov","a,b");
3475         pic14_emitcode("rrc","a");
3476         aopPut(AOP(result),"c",0);
3477 }
3478
3479 /*-----------------------------------------------------------------*/
3480 /* genModOneByte : 8 bit modulus                                                                   */
3481 /*-----------------------------------------------------------------*/
3482 static void genModOneByte (operand *left,
3483                                                    operand *right,
3484                                                    operand *result)
3485 {
3486         sym_link *opetype = operandType(result);
3487         char *l ;
3488         symbol *lbl ;
3489         
3490         FENTRY;
3491         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3492         /* signed or unsigned */
3493         if (SPEC_USIGN(opetype)) {
3494                 /* unsigned is easy */
3495                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3496                 l = aopGet(AOP(left),0,FALSE,FALSE);
3497                 MOVA(l);        
3498                 pic14_emitcode("div","ab");
3499                 aopPut(AOP(result),"b",0);
3500                 return ;
3501         }
3502         
3503         /* signed is a little bit more difficult */
3504         
3505         /* save the signs of the operands */
3506         l = aopGet(AOP(left),0,FALSE,FALSE);      
3507         MOVA(l);
3508         
3509         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3510         pic14_emitcode("push","acc"); /* save it on the stack */
3511         
3512         /* now sign adjust for both left & right */
3513         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3514         MOVA(l);
3515         
3516         lbl = newiTempLabel(NULL);
3517         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3518         pic14_emitcode("cpl","a");   
3519         pic14_emitcode("inc","a");
3520         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3521         pic14_emitcode("mov","b,a"); 
3522         
3523         /* sign adjust left side */
3524         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3525         MOVA(l);
3526         
3527         lbl = newiTempLabel(NULL);
3528         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3529         pic14_emitcode("cpl","a");   
3530         pic14_emitcode("inc","a");
3531         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3532         
3533         /* now the multiplication */
3534         pic14_emitcode("div","ab");
3535         /* we are interested in the lower order
3536         only */
3537         lbl = newiTempLabel(NULL);
3538         pic14_emitcode("pop","acc");     
3539         /* if there was an over flow we don't 
3540         adjust the sign of the result */
3541         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3542         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3543         CLRC ;
3544         pic14_emitcode("clr","a");
3545         pic14_emitcode("subb","a,b");
3546         pic14_emitcode("mov","b,a");
3547         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3548         
3549         /* now we are done */
3550         aopPut(AOP(result),"b",0);
3551         
3552 }
3553
3554 /*-----------------------------------------------------------------*/
3555 /* genMod - generates code for division                                                    */
3556 /*-----------------------------------------------------------------*/
3557 static void genMod (iCode *ic)
3558 {
3559         operand *left = IC_LEFT(ic);
3560         operand *right = IC_RIGHT(ic);
3561         operand *result= IC_RESULT(ic);  
3562         
3563         FENTRY;
3564         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3565         /* assign the amsops */
3566         aopOp (left,ic,FALSE);
3567         aopOp (right,ic,FALSE);
3568         aopOp (result,ic,TRUE);
3569         
3570         /* special cases first */
3571         /* both are bits */
3572         if (AOP_TYPE(left) == AOP_CRY &&
3573                 AOP_TYPE(right)== AOP_CRY) {
3574                 genModbits(left,right,result);
3575                 goto release ;
3576         }
3577         
3578         /* if both are of size == 1 */
3579         if (AOP_SIZE(left) == 1 &&
3580                 AOP_SIZE(right) == 1 ) {
3581                 genModOneByte(left,right,result);
3582                 goto release ;
3583         }
3584         
3585         /* should have been converted to function call */
3586         assert(0);
3587         
3588 release :
3589         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3590         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3591         freeAsmop(result,NULL,ic,TRUE); 
3592 }
3593
3594 /*-----------------------------------------------------------------*/
3595 /* genIfxJump :- will create a jump depending on the ifx                   */
3596 /*-----------------------------------------------------------------*/
3597 /*
3598 note: May need to add parameter to indicate when a variable is in bit space.
3599 */
3600 static void genIfxJump (iCode *ic, char *jval)
3601 {
3602         
3603         FENTRY;
3604         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3605         /* if true label then we jump if condition
3606         supplied is true */
3607         if ( IC_TRUE(ic) ) {
3608                 
3609                 if(strcmp(jval,"a") == 0)
3610                         emitSKPZ;
3611                 else if (strcmp(jval,"c") == 0)
3612                         emitSKPC;
3613                 else {
3614                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3615                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3616                 }
3617                 
3618                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3619                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3620                 
3621         }
3622         else {
3623                 /* false label is present */
3624                 if(strcmp(jval,"a") == 0)
3625                         emitSKPNZ;
3626                 else if (strcmp(jval,"c") == 0)
3627                         emitSKPNC;
3628                 else {
3629                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3630                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3631                 }
3632                 
3633                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3634                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3635                 
3636         }
3637         
3638         
3639         /* mark the icode as generated */
3640         ic->generated = 1;
3641 }
3642
3643 /*-----------------------------------------------------------------*/
3644 /* genSkip                                                                                                                 */
3645 /*-----------------------------------------------------------------*/
3646 static void genSkip(iCode *ifx,int status_bit)
3647 {
3648         FENTRY;
3649         if(!ifx)
3650                 return;
3651         
3652         if ( IC_TRUE(ifx) ) {
3653                 switch(status_bit) {
3654                 case 'z':
3655                         emitSKPNZ;
3656                         break;
3657                         
3658                 case 'c':
3659                         emitSKPNC;
3660                         break;
3661                         
3662                 case 'd':
3663                         emitSKPDC;
3664                         break;
3665                         
3666                 }
3667                 
3668                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3669                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3670                 
3671         } else {
3672                 
3673                 switch(status_bit) {
3674                         
3675                 case 'z':
3676                         emitSKPZ;
3677                         break;
3678                         
3679                 case 'c':
3680                         emitSKPC;
3681                         break;
3682                         
3683                 case 'd':
3684                         emitSKPDC;
3685                         break;
3686                 }
3687                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3688                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3689                 
3690         }
3691         
3692 }
3693
3694 /*-----------------------------------------------------------------*/
3695 /* genSkipc                                                                                                        */
3696 /*-----------------------------------------------------------------*/
3697 static void genSkipc(resolvedIfx *rifx)
3698 {
3699         FENTRY;
3700         if(!rifx)
3701                 return;
3702         
3703         if(rifx->condition)
3704                 emitSKPC;
3705         else
3706                 emitSKPNC;
3707         
3708         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3709         rifx->generated = 1;
3710 }
3711
3712 /*-----------------------------------------------------------------*/
3713 /* genSkipz2                                                                                                       */
3714 /*-----------------------------------------------------------------*/
3715 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3716 {
3717         FENTRY;
3718         if(!rifx)
3719                 return;
3720         
3721         if( (rifx->condition ^ invert_condition) & 1)
3722                 emitSKPZ;
3723         else
3724                 emitSKPNZ;
3725         
3726         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3727         rifx->generated = 1;
3728 }
3729
3730 /*-----------------------------------------------------------------*/
3731 /* genSkipz                                                        */
3732 /*-----------------------------------------------------------------*/
3733 static void genSkipz(iCode *ifx, int condition)
3734 {
3735         FENTRY;
3736         if(!ifx)
3737                 return;
3738         
3739         if(condition)
3740                 emitSKPNZ;
3741         else
3742                 emitSKPZ;
3743         
3744         if ( IC_TRUE(ifx) )
3745                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3746         else
3747                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3748         
3749         if ( IC_TRUE(ifx) )
3750                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3751         else
3752                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3753         
3754 }
3755 /*-----------------------------------------------------------------*/
3756 /* genSkipCond                                                     */
3757 /*-----------------------------------------------------------------*/
3758 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3759 {
3760         FENTRY;
3761         if(!rifx)
3762                 return;
3763         
3764         if(rifx->condition)
3765                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3766         else
3767                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3768         
3769         
3770         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3771         rifx->generated = 1;
3772 }
3773
3774 #if 0
3775 /*-----------------------------------------------------------------*/
3776 /* genChkZeroes :- greater or less than comparison                 */
3777 /*     For each byte in a literal that is zero, inclusive or the   */
3778 /*     the corresponding byte in the operand with W                */
3779 /*     returns true if any of the bytes are zero                   */
3780 /*-----------------------------------------------------------------*/
3781 static int genChkZeroes(operand *op, int lit,  int size)
3782 {
3783         
3784         int i;
3785         int flag =1;
3786         
3787         while(size--) {
3788                 i = (lit >> (size*8)) & 0xff;
3789                 
3790                 if(i==0) {
3791                         if(flag) 
3792                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3793                         else
3794                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3795                         flag = 0;
3796                 }
3797         }
3798         
3799         return (flag==0);
3800 }
3801 #endif
3802
3803 /*-----------------------------------------------------------------*/
3804 /* genCmp :- greater or less than comparison                       */
3805 /*-----------------------------------------------------------------*/
3806 static void genCmp (operand *left,operand *right,
3807                                         operand *result, iCode *ifx, int sign)
3808 {
3809         int size; //, offset = 0 ;
3810         unsigned long lit = 0L,i = 0;
3811         resolvedIfx rFalseIfx;
3812         //  resolvedIfx rTrueIfx;
3813         symbol *truelbl;
3814
3815         FENTRY;
3816         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3817         /*
3818         if(ifx) {
3819         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3820         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3821         }
3822         */
3823         
3824         resolveIfx(&rFalseIfx,ifx);
3825         truelbl  = newiTempLabel(NULL);
3826         size = max(AOP_SIZE(left),AOP_SIZE(right));
3827         
3828         DEBUGpic14_AopType(__LINE__,left,right,result);
3829         
3830 #define _swapp
3831         
3832         /* if literal is on the right then swap with left */
3833         if ((AOP_TYPE(right) == AOP_LIT)) {
3834                 operand *tmp = right ;
3835                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
3836                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3837 #ifdef _swapp
3838                 
3839                 lit = (lit - 1) & mask;
3840                 right = left;
3841                 left = tmp;
3842                 rFalseIfx.condition ^= 1;
3843 #endif
3844                 
3845         } else if ((AOP_TYPE(left) == AOP_LIT)) {
3846                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3847         }
3848         
3849         
3850         //if(IC_TRUE(ifx) == NULL)
3851         /* if left & right are bit variables */
3852         if (AOP_TYPE(left) == AOP_CRY &&
3853                 AOP_TYPE(right) == AOP_CRY ) {
3854                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
3855                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
3856         } else {
3857         /* subtract right from left if at the
3858         end the carry flag is set then we know that
3859                 left is greater than right */
3860                 
3861                 symbol *lbl  = newiTempLabel(NULL);
3862                 
3863 #ifndef _swapp
3864                 if(AOP_TYPE(right) == AOP_LIT) {
3865                         
3866                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3867                         
3868                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
3869                         
3870                         /* special cases */
3871                         
3872                         if(lit == 0) {
3873                                 
3874                                 if(sign != 0) 
3875                                         genSkipCond(&rFalseIfx,left,size-1,7);
3876                                 else 
3877                                         /* no need to compare to 0...*/
3878                                         /* NOTE: this is a de-generate compare that most certainly 
3879                                         *       creates some dead code. */
3880                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
3881                                 
3882                                 if(ifx) ifx->generated = 1;
3883                                 return;
3884                                 
3885                         }
3886                         size--;
3887                         
3888                         if(size == 0) {
3889                                 //i = (lit >> (size*8)) & 0xff;
3890                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3891                                 
3892                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3893                                 
3894                                 i = ((0-lit) & 0xff);
3895                                 if(sign) {
3896                                         if( i == 0x81) { 
3897                                         /* lit is 0x7f, all signed chars are less than
3898                                                 * this except for 0x7f itself */
3899                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
3900                                                 genSkipz2(&rFalseIfx,0);
3901                                         } else {
3902                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
3903                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
3904                                                 genSkipc(&rFalseIfx);
3905                                         }
3906                                         
3907                                 } else {
3908                                         if(lit == 1) {
3909                                                 genSkipz2(&rFalseIfx,1);
3910                                         } else {
3911                                                 emitpcode(POC_ADDLW, popGetLit(i));
3912                                                 genSkipc(&rFalseIfx);
3913                                         }
3914                                 }
3915                                 
3916                                 if(ifx) ifx->generated = 1;
3917                                 return;
3918                         }
3919                         
3920                         /* chars are out of the way. now do ints and longs */
3921                         
3922                         
3923                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
3924                         
3925                         /* special cases */
3926                         
3927                         if(sign) {
3928                                 
3929                                 if(lit == 0) {
3930                                         genSkipCond(&rFalseIfx,left,size,7);
3931                                         if(ifx) ifx->generated = 1;
3932                                         return;
3933                                 }
3934                                 
3935                                 if(lit <0x100) {
3936                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3937                                         
3938                                         //rFalseIfx.condition ^= 1;
3939                                         //genSkipCond(&rFalseIfx,left,size,7);
3940                                         //rFalseIfx.condition ^= 1;
3941                                         
3942                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
3943                                         if(rFalseIfx.condition)
3944                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
3945                                         else
3946                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3947                                         
3948                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
3949                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
3950                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
3951                                         
3952                                         while(size > 1)
3953                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
3954                                         
3955                                         if(rFalseIfx.condition) {
3956                                                 emitSKPZ;
3957                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
3958                                                 
3959                                         } else {
3960                                                 emitSKPNZ;
3961                                         }
3962                                         
3963                                         genSkipc(&rFalseIfx);
3964                                         emitpLabel(truelbl->key);
3965                                         if(ifx) ifx->generated = 1;
3966                                         return;
3967                                         
3968                                 }
3969                                 
3970                                 if(size == 1) {
3971                                         
3972                                         if( (lit & 0xff) == 0) {
3973                                                 /* lower byte is zero */
3974                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3975                                                 i = ((lit >> 8) & 0xff) ^0x80;
3976                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3977                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
3978                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3979                                                 genSkipc(&rFalseIfx);
3980                                                 
3981                                                 
3982                                                 if(ifx) ifx->generated = 1;
3983                                                 return;
3984                                                 
3985                                         }
3986                                 } else {
3987                                         /* Special cases for signed longs */
3988                                         if( (lit & 0xffffff) == 0) {
3989                                                 /* lower byte is zero */
3990                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
3991                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
3992                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
3993                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
3994                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
3995                                                 genSkipc(&rFalseIfx);
3996                                                 
3997                                                 
3998                                                 if(ifx) ifx->generated = 1;
3999                                                 return;
4000                                                 
4001                                         }
4002                                         
4003                                 }
4004                                 
4005                                 
4006                                 if(lit & (0x80 << (size*8))) {
4007                                         /* lit is negative */
4008                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4009                                         
4010                                         //genSkipCond(&rFalseIfx,left,size,7);
4011                                         
4012                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4013                                         
4014                                         if(rFalseIfx.condition)
4015                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4016                                         else
4017                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4018                                         
4019                                         
4020                                 } else {
4021                                         /* lit is positive */
4022                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4023                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4024                                         if(rFalseIfx.condition)
4025                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4026                                         else
4027                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4028                                         
4029                                 }
4030                                 
4031                                 /* There are no more special cases, so perform a general compare */
4032                                 
4033                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4034                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4035                                 
4036                                 while(size--) {
4037                                         
4038                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4039                                         emitSKPNZ;
4040                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4041                                 }
4042                                 //rFalseIfx.condition ^= 1;
4043                                 genSkipc(&rFalseIfx);
4044                                 
4045                                 emitpLabel(truelbl->key);
4046                                 
4047                                 if(ifx) ifx->generated = 1;
4048                                 return;
4049                                 
4050                                 
4051                         }
4052
4053
4054                         /* sign is out of the way. So now do an unsigned compare */
4055                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4056
4057
4058                         /* General case - compare to an unsigned literal on the right.*/
4059
4060                         i = (lit >> (size*8)) & 0xff;
4061                         emitpcode(POC_MOVLW, popGetLit(i));
4062                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4063                         while(size--) {
4064                                 i = (lit >> (size*8)) & 0xff;
4065                                 
4066                                 if(i) {
4067                                         emitpcode(POC_MOVLW, popGetLit(i));
4068                                         emitSKPNZ;
4069                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4070                                 } else {
4071                                 /* this byte of the lit is zero, 
4072                                         *if it's not the last then OR in the variable */
4073                                         if(size)
4074                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4075                                 }
4076                         }
4077
4078
4079                 emitpLabel(lbl->key);
4080                 //if(emitFinalCheck)
4081                 genSkipc(&rFalseIfx);
4082                 if(sign)
4083                         emitpLabel(truelbl->key);
4084
4085                 if(ifx) ifx->generated = 1;
4086                 return;
4087
4088
4089                 }
4090 #endif  // _swapp
4091
4092                 if(AOP_TYPE(left) == AOP_LIT) {
4093                         //symbol *lbl = newiTempLabel(NULL);
4094                         
4095                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4096                         
4097                         
4098                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4099                         
4100                         /* Special cases */
4101                         if((lit == 0) && (sign == 0)){
4102                                 
4103                                 size--;
4104                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4105                                 while(size) 
4106                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4107                                 
4108                                 genSkipz2(&rFalseIfx,0);
4109                                 if(ifx) ifx->generated = 1;
4110                                 return;
4111                         }
4112                         
4113                         if(size==1) {
4114                                 /* Special cases */
4115                                 lit &= 0xff;
4116                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4117                                         /* degenerate compare can never be true */
4118                                         if(rFalseIfx.condition == 0)
4119                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4120                                         
4121                                         if(ifx) ifx->generated = 1;
4122                                         return;
4123                                 }
4124                                 
4125                                 if(sign) {
4126                                         /* signed comparisons to a literal byte */
4127                                         
4128                                         int lp1 = (lit+1) & 0xff;
4129                                         
4130                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4131                                         switch (lp1) {
4132                                         case 0:
4133                                                 rFalseIfx.condition ^= 1;
4134                                                 genSkipCond(&rFalseIfx,right,0,7);
4135                                                 break;
4136                                         case 0x7f:
4137                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4138                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4139                                                 genSkipz2(&rFalseIfx,1);
4140                                                 break;
4141                                         default:
4142                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4143                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4144                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4145                                                 rFalseIfx.condition ^= 1;
4146                                                 genSkipc(&rFalseIfx);
4147                                                 break;
4148                                         }
4149                                         if(ifx) ifx->generated = 1;
4150                                 } else {
4151                                         /* unsigned comparisons to a literal byte */
4152                                         
4153                                         switch(lit & 0xff ) {
4154                                         case 0:
4155                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4156                                                 genSkipz2(&rFalseIfx,0);
4157                                                 if(ifx) ifx->generated = 1;
4158                                                 break;
4159                                         case 0x7f:
4160                                                 genSkipCond(&rFalseIfx,right,0,7);
4161                                                 if(ifx) ifx->generated = 1;
4162                                                 break;
4163                                                 
4164                                         default:
4165                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4166                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4167                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4168                                                 rFalseIfx.condition ^= 1;
4169                                                 if (AOP_TYPE(result) == AOP_CRY) {
4170                                                         genSkipc(&rFalseIfx);
4171                                                         if(ifx) ifx->generated = 1;
4172                                                 } else {
4173                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4174                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4175                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4176                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4177                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4178                                                 }       
4179                                                 break;
4180                                         }
4181                                 }
4182                                 
4183                                 //goto check_carry;
4184                                 return;
4185                                 
4186                         } else {
4187                                 
4188                                 /* Size is greater than 1 */
4189                                 
4190                                 if(sign) {
4191                                         int lp1 = lit+1;
4192                                         
4193                                         size--;
4194                                         
4195                                         if(lp1 == 0) {
4196                                                 /* this means lit = 0xffffffff, or -1 */
4197                                                 
4198                                                 
4199                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4200                                                 rFalseIfx.condition ^= 1;
4201                                                 genSkipCond(&rFalseIfx,right,size,7);
4202                                                 if(ifx) ifx->generated = 1;
4203                                                 return;
4204                                         }
4205                                         
4206                                         if(lit == 0) {
4207                                                 int s = size;
4208                                                 
4209                                                 if(rFalseIfx.condition) {
4210                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4211                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4212                                                 }
4213                                                 
4214                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4215                                                 while(size--)
4216                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4217                                                 
4218                                                 
4219                                                 emitSKPZ;
4220                                                 if(rFalseIfx.condition) {
4221                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4222                                                         emitpLabel(truelbl->key);
4223                                                 }else {
4224                                                         rFalseIfx.condition ^= 1;
4225                                                         genSkipCond(&rFalseIfx,right,s,7);
4226                                                 }
4227                                                 
4228                                                 if(ifx) ifx->generated = 1;
4229                                                 return;
4230                                         }
4231                                         
4232                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4233                                                 /* lower byte of signed word is zero */
4234                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4235                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4236                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4237                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4238                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4239                                                 rFalseIfx.condition ^= 1;
4240                                                 genSkipc(&rFalseIfx);
4241                                                 
4242                                                 
4243                                                 if(ifx) ifx->generated = 1;
4244                                                 return;
4245                                         }
4246                                         
4247                                         if(lit & (0x80 << (size*8))) {
4248                                                 /* Lit is less than zero */
4249                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4250                                                 //rFalseIfx.condition ^= 1;
4251                                                 //genSkipCond(&rFalseIfx,left,size,7);
4252                                                 //rFalseIfx.condition ^= 1;
4253                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4254                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4255                                                 
4256                                                 if(rFalseIfx.condition)
4257                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4258                                                 else
4259                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4260                                                 
4261                                                 
4262                                         } else {
4263                                                 /* Lit is greater than or equal to zero */
4264                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4265                                                 //rFalseIfx.condition ^= 1;
4266                                                 //genSkipCond(&rFalseIfx,right,size,7);
4267                                                 //rFalseIfx.condition ^= 1;
4268                                                 
4269                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4270                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4271                                                 
4272                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4273                                                 if(rFalseIfx.condition)
4274                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4275                                                 else
4276                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4277                                                 
4278                                         }
4279                                         
4280                                         
4281                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4282                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4283                                         
4284                                         while(size--) {
4285                                                 
4286                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4287                                                 emitSKPNZ;
4288                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4289                                         }
4290                                         rFalseIfx.condition ^= 1;
4291                                         //rFalseIfx.condition = 1;
4292                                         genSkipc(&rFalseIfx);
4293                                         
4294                                         emitpLabel(truelbl->key);
4295                                         
4296                                         if(ifx) ifx->generated = 1;
4297                                         return;
4298                                         // end of if (sign)
4299                                 } else {
4300                                         
4301                                         /* compare word or long to an unsigned literal on the right.*/
4302                                         
4303                                         
4304                                         size--;
4305                                         if(lit < 0xff) {
4306                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4307                                                 switch (lit) {
4308                                                 case 0:
4309                                                         break; /* handled above */
4310                                                 /*
4311                                                 case 0xff:
4312                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4313                                                         while(size--)
4314                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4315                                                         genSkipz2(&rFalseIfx,0);
4316                                                         break;
4317                                                 */
4318                                                 default:
4319                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4320                                                         while(--size)
4321                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4322                                                         
4323                                                         emitSKPZ;
4324                                                         if(rFalseIfx.condition)
4325                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4326                                                         else
4327                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4328                                                         
4329                                                         
4330                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4331                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4332                                                         
4333                                                         rFalseIfx.condition ^= 1;
4334                                                         genSkipc(&rFalseIfx);
4335                                                 }
4336                                                 
4337                                                 emitpLabel(truelbl->key);
4338                                                 
4339                                                 if(ifx) ifx->generated = 1;
4340                                                 return;
4341                                         }
4342                                         
4343                                         
4344                                         lit++;
4345                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4346                                         i = (lit >> (size*8)) & 0xff;
4347                                         
4348                                         emitpcode(POC_MOVLW, popGetLit(i));
4349                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4350                                         
4351                                         while(size--) {
4352                                                 i = (lit >> (size*8)) & 0xff;
4353                                                 
4354                                                 if(i) {
4355                                                         emitpcode(POC_MOVLW, popGetLit(i));
4356                                                         emitSKPNZ;
4357                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4358                                                 } else {
4359                                                 /* this byte of the lit is zero, 
4360                                                         *if it's not the last then OR in the variable */
4361                                                         if(size)
4362                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4363                                                 }
4364                                         }
4365                                         
4366                                         
4367                                         emitpLabel(lbl->key);
4368                                         
4369                                         rFalseIfx.condition ^= 1;
4370                                         genSkipc(&rFalseIfx);
4371                                 }
4372                                 
4373                                 if(sign)
4374                                         emitpLabel(truelbl->key);
4375                                 if(ifx) ifx->generated = 1;
4376                                 return;
4377                         }
4378                 }
4379                 /* Compare two variables */
4380                 
4381                 DEBUGpic14_emitcode(";sign","%d",sign);
4382                 
4383                 size--;
4384                 if(sign) {
4385                         /* Sigh. thus sucks... */
4386                         if(size) {
4387                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4388                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4389                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4390                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4391                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4392                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4393                         } else {
4394                                 /* Signed char comparison */
4395                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4396                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4397                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4398                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4399                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4400                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4401                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4402                                 
4403                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4404                                 genSkipc(&rFalseIfx);
4405                                 
4406                                 if(ifx) ifx->generated = 1;
4407                                 return;
4408                         }
4409                         
4410                 } else {
4411                         
4412                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4413                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4414                 }
4415                 
4416                 
4417                 /* The rest of the bytes of a multi-byte compare */
4418                 while (size) {
4419                         
4420                         emitSKPZ;
4421                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4422                         size--;
4423                         
4424                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4425                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4426                         
4427                         
4428                 }
4429                 
4430                 emitpLabel(lbl->key);
4431                 
4432                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4433                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4434                         (AOP_TYPE(result) == AOP_REG)) {
4435                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4436                         emitpcode(POC_RLF, popGet(AOP(result),0));
4437                 } else {
4438                         genSkipc(&rFalseIfx);
4439                 }       
4440                 //genSkipc(&rFalseIfx);
4441                 if(ifx) ifx->generated = 1;
4442                 
4443                 return;
4444                 
4445         }
4446         
4447         // check_carry:
4448         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4449                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4450                 pic14_outBitC(result);
4451         } else {
4452                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4453                 /* if the result is used in the next
4454                 ifx conditional branch then generate
4455                 code a little differently */
4456                 if (ifx )
4457                         genIfxJump (ifx,"c");
4458                 else
4459                         pic14_outBitC(result);
4460                 /* leave the result in acc */
4461         }
4462         
4463 }
4464
4465 /*-----------------------------------------------------------------*/
4466 /* genCmpGt :- greater than comparison                             */
4467 /*-----------------------------------------------------------------*/
4468 static void genCmpGt (iCode *ic, iCode *ifx)
4469 {
4470         operand *left, *right, *result;
4471         sym_link *letype , *retype;
4472         int sign ;
4473         
4474         FENTRY;
4475         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4476         left = IC_LEFT(ic);
4477         right= IC_RIGHT(ic);
4478         result = IC_RESULT(ic);
4479         
4480         letype = getSpec(operandType(left));
4481         retype =getSpec(operandType(right));
4482         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4483         /* assign the amsops */
4484         aopOp (left,ic,FALSE);
4485         aopOp (right,ic,FALSE);
4486         aopOp (result,ic,TRUE);
4487         
4488         genCmp(right, left, result, ifx, sign);
4489         
4490         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4491         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4492         freeAsmop(result,NULL,ic,TRUE); 
4493 }
4494
4495 /*-----------------------------------------------------------------*/
4496 /* genCmpLt - less than comparisons                                */
4497 /*-----------------------------------------------------------------*/
4498 static void genCmpLt (iCode *ic, iCode *ifx)
4499 {
4500         operand *left, *right, *result;
4501         sym_link *letype , *retype;
4502         int sign ;
4503         
4504         FENTRY;
4505         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4506         left = IC_LEFT(ic);
4507         right= IC_RIGHT(ic);
4508         result = IC_RESULT(ic);
4509         
4510         letype = getSpec(operandType(left));
4511         retype =getSpec(operandType(right));
4512         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4513         
4514         /* assign the amsops */
4515         aopOp (left,ic,FALSE);
4516         aopOp (right,ic,FALSE);
4517         aopOp (result,ic,TRUE);
4518         
4519         genCmp(left, right, result, ifx, sign);
4520         
4521         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4522         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4523         freeAsmop(result,NULL,ic,TRUE); 
4524 }
4525
4526 /*-----------------------------------------------------------------*/
4527 /* genc16bit2lit - compare a 16 bit value to a literal             */
4528 /*-----------------------------------------------------------------*/
4529 static void genc16bit2lit(operand *op, int lit, int offset)
4530 {
4531         int i;
4532         
4533         FENTRY;
4534         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4535         if( (lit&0xff) == 0) 
4536                 i=1;
4537         else
4538                 i=0;
4539         
4540         switch( BYTEofLONG(lit,i)) { 
4541         case 0:
4542                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4543                 break;
4544         case 1:
4545                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4546                 break;
4547         case 0xff:
4548                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4549                 break;
4550         default:
4551                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4552                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4553         }
4554         
4555         i ^= 1;
4556         
4557         switch( BYTEofLONG(lit,i)) { 
4558         case 0:
4559                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4560                 break;
4561         case 1:
4562                 emitSKPNZ;
4563                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4564                 break;
4565         case 0xff:
4566                 emitSKPNZ;
4567                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4568                 break;
4569         default:
4570                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4571                 emitSKPNZ;
4572                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4573                 
4574         }
4575         
4576 }
4577
4578 /*-----------------------------------------------------------------*/
4579 /* gencjneshort - compare and jump if not equal                    */
4580 /*-----------------------------------------------------------------*/
4581 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4582 {
4583         int size = max(AOP_SIZE(left),AOP_SIZE(right));
4584         int offset = 0;
4585         int res_offset = 0;  /* the result may be a different size then left or right */
4586         int res_size = AOP_SIZE(result);
4587         resolvedIfx rIfx;
4588         symbol *lbl;
4589         
4590         unsigned long lit = 0L;
4591         FENTRY;
4592         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4593           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4594           return;
4595         }
4596         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4597         DEBUGpic14_AopType(__LINE__,left,right,result);
4598         if(result)
4599                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4600         resolveIfx(&rIfx,ifx);
4601         lbl =  newiTempLabel(NULL);
4602         
4603         
4604         /* if the left side is a literal or 
4605         if the right is in a pointer register and left 
4606         is not */
4607         if ((AOP_TYPE(left) == AOP_LIT) || 
4608                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4609                 operand *t = right;
4610                 right = left;
4611                 left = t;
4612         }
4613         if(AOP_TYPE(right) == AOP_LIT)
4614                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4615         
4616         /* if the right side is a literal then anything goes */
4617         if (AOP_TYPE(right) == AOP_LIT &&
4618                 AOP_TYPE(left) != AOP_DIR ) {
4619                 switch(size) {
4620                 case 2:
4621                         genc16bit2lit(left, lit, 0);
4622                         emitSKPNZ;
4623                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4624                         break;
4625                 default:
4626                         while (size--) {
4627                                 if(lit & 0xff) {
4628                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4629                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4630                                 } else {
4631                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4632                                 }
4633                                 
4634                                 emitSKPNZ;
4635                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4636                                 offset++;
4637                                 if(res_offset < res_size-1)
4638                                         res_offset++;
4639                                 lit >>= 8;
4640                         }
4641                         break;
4642                 }
4643         }
4644         
4645         /* if the right side is in a register or in direct space or
4646         if the left is a pointer register & right is not */    
4647         else if (AOP_TYPE(right) == AOP_REG ||
4648                 AOP_TYPE(right) == AOP_DIR || 
4649                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4650                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4651                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4652                 int lbl_key = lbl->key;
4653                 
4654                 if(result) {
4655                         if (AOP_TYPE(result) != AOP_CRY)
4656                                 emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4657                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4658                 }else {
4659                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4660                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4661                                 __FUNCTION__,__LINE__);
4662                         return;
4663                 }
4664                 
4665                 /*     switch(size) { */
4666                 /*     case 2: */
4667                 /*       genc16bit2lit(left, lit, 0); */
4668                 /*       emitSKPNZ; */
4669                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4670                 /*       break; */
4671                 /*     default: */
4672                 while (size--) {
4673                         int emit_skip=1;
4674                         if((AOP_TYPE(left) == AOP_DIR) && 
4675                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4676                                 
4677                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4678                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4679                                 
4680                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4681                                 
4682                                 switch (lit & 0xff) {
4683                                 case 0:
4684                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4685                                         break;
4686                                 case 1:
4687                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4688                                         emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4689                                         //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4690                                         emit_skip=0;
4691                                         break;
4692                                 case 0xff:
4693                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4694                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4695                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4696                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4697                                         emit_skip=0;
4698                                         break;
4699                                 default:
4700                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4701                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4702                                 }
4703                                 lit >>= 8;
4704                                 
4705                         } else {
4706                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4707                         }
4708                         if(emit_skip) {
4709                                 if(AOP_TYPE(result) == AOP_CRY) {
4710                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4711                                         if(rIfx.condition)
4712                                                 emitSKPNZ;
4713                                         else
4714                                                 emitSKPZ;
4715                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4716                                 } else {
4717                                         /* fix me. probably need to check result size too */
4718                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
4719                                         if(rIfx.condition)
4720                                                 emitSKPZ;
4721                                         else
4722                                                 emitSKPNZ;
4723                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4724                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4725                                 }
4726                                 if(ifx)
4727                                         ifx->generated=1;
4728                         }
4729                         emit_skip++;
4730                         offset++;
4731                         if(res_offset < res_size-1)
4732                                 res_offset++;
4733                 }
4734                 /*       break; */
4735                 /*     } */
4736         } else if(AOP_TYPE(right) == AOP_REG &&
4737                 AOP_TYPE(left) != AOP_DIR){
4738                 
4739                 while(size--) {
4740                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4741                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4742                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4743                         if(rIfx.condition)
4744                                 emitSKPNZ;
4745                         else
4746                                 emitSKPZ;
4747                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4748                         offset++;
4749                         if(res_offset < res_size-1)
4750                                 res_offset++;
4751                 }
4752                 
4753         }else{
4754                 /* right is a pointer reg need both a & b */
4755                 while(size--) {
4756                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
4757                         if(strcmp(l,"b"))
4758                                 pic14_emitcode("mov","b,%s",l);
4759                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
4760                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4761                         offset++;
4762                 }
4763         }
4764         
4765         emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4766         if(!rIfx.condition)
4767                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4768         
4769         emitpLabel(lbl->key);
4770         
4771         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4772         
4773         if(ifx)
4774                 ifx->generated = 1;
4775 }
4776
4777 #if 0
4778 /*-----------------------------------------------------------------*/
4779 /* gencjne - compare and jump if not equal                         */
4780 /*-----------------------------------------------------------------*/
4781 static void gencjne(operand *left, operand *right, iCode *ifx)
4782 {
4783         symbol *tlbl  = newiTempLabel(NULL);
4784         
4785         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4786         gencjneshort(left, right, lbl);
4787         
4788         pic14_emitcode("mov","a,%s",one);
4789         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4790         pic14_emitcode("","%05d_DS_:",lbl->key+100);
4791         pic14_emitcode("clr","a");
4792         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
4793         
4794         emitpLabel(lbl->key);
4795         emitpLabel(tlbl->key);
4796         
4797 }
4798 #endif
4799
4800 /*-----------------------------------------------------------------*/
4801 /* genCmpEq - generates code for equal to                          */
4802 /*-----------------------------------------------------------------*/
4803 static void genCmpEq (iCode *ic, iCode *ifx)
4804 {
4805         operand *left, *right, *result;
4806         unsigned long lit = 0L;
4807         int size,offset=0;
4808         
4809         FENTRY;
4810         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4811         
4812         if(ifx)
4813                 DEBUGpic14_emitcode ("; ifx is non-null","");
4814         else
4815                 DEBUGpic14_emitcode ("; ifx is null","");
4816         
4817         aopOp((left=IC_LEFT(ic)),ic,FALSE);
4818         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4819         aopOp((result=IC_RESULT(ic)),ic,TRUE);
4820         
4821         size = max(AOP_SIZE(left),AOP_SIZE(right));
4822         
4823         DEBUGpic14_AopType(__LINE__,left,right,result);
4824         
4825         /* if literal, literal on the right or 
4826         if the right is in a pointer register and left 
4827         is not */
4828         if (aop_isLitLike (AOP(IC_LEFT(ic)))
4829                         || (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4830                 operand *tmp = right ;
4831                 right = left;
4832                 left = tmp;
4833         }
4834         
4835         
4836         if(ifx && !AOP_SIZE(result)){
4837                 symbol *tlbl;
4838                 /* if they are both bit variables */
4839                 if (AOP_TYPE(left) == AOP_CRY &&
4840                         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
4841                         if(AOP_TYPE(right) == AOP_LIT){
4842                                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4843                                 if(lit == 0L){
4844                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4845                                         pic14_emitcode("cpl","c");
4846                                 } else if(lit == 1L) {
4847                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4848                                 } else {
4849                                         pic14_emitcode("clr","c");
4850                                 }
4851                                 /* AOP_TYPE(right) == AOP_CRY */
4852                         } else {
4853                                 symbol *lbl = newiTempLabel(NULL);
4854                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
4855                                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
4856                                 pic14_emitcode("cpl","c");
4857                                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
4858                         }
4859                         /* if true label then we jump if condition
4860                         supplied is true */
4861                         tlbl = newiTempLabel(NULL);
4862                         if ( IC_TRUE(ifx) ) {
4863                                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
4864                                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
4865                         } else {
4866                                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
4867                                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
4868                         }
4869                         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
4870                         
4871                         {
4872                                 /* left and right are both bit variables, result is carry */
4873                                 resolvedIfx rIfx;
4874                                 
4875                                 resolveIfx(&rIfx,ifx);
4876                                 
4877                                 emitpcode(POC_MOVLW,popGet(AOP(left),0));
4878                                 emitpcode(POC_ANDFW,popGet(AOP(left),0));
4879                                 emitpcode(POC_BTFSC,popGet(AOP(right),0));
4880                                 emitpcode(POC_ANDLW,popGet(AOP(left),0));
4881                                 genSkipz2(&rIfx,0);
4882                         }
4883                 } else {
4884                         
4885                         /* They're not both bit variables. Is the right a literal? */
4886                         if(AOP_TYPE(right) == AOP_LIT) {
4887                                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4888                                 
4889                                 switch(size) {
4890                                         
4891                                 case 1:
4892                                         switch(lit & 0xff) {
4893                                         case 1:
4894                                                 if ( IC_TRUE(ifx) ) {
4895                                                         emitpcode(POC_DECFW,popGet(AOP(left),offset));
4896                                                         emitSKPNZ;
4897                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4898                                                 } else {
4899                                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4900                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4901                                                 }
4902                                                 break;
4903                                         case 0xff:
4904                                                 if ( IC_TRUE(ifx) ) {
4905                                                         emitpcode(POC_INCFW,popGet(AOP(left),offset));
4906                                                         emitSKPNZ;
4907                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4908                                                 } else {
4909                                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4910                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4911                                                 }
4912                                                 break;
4913                                         default:
4914                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4915                                                 if(lit)
4916                                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4917                                                 genSkip(ifx,'z');
4918                                         }
4919                                         
4920                                         
4921                                         /* end of size == 1 */
4922                                         break;
4923                                         
4924                                         case 2:
4925                                                 genc16bit2lit(left,lit,offset);
4926                                                 genSkip(ifx,'z');
4927                                                 break;
4928                                                 /* end of size == 2 */
4929                                                 
4930                                         default:
4931                                                 /* size is 4 */
4932                                                 if(lit==0) {
4933                                                         emitpcode(POC_MOVFW,popGet(AOP(left),0));
4934                                                         emitpcode(POC_IORFW,popGet(AOP(left),1));
4935                                                         emitpcode(POC_IORFW,popGet(AOP(left),2));
4936                                                         emitpcode(POC_IORFW,popGet(AOP(left),3));
4937                                                         
4938                                                 } else {
4939                                                         
4940                                                         /* search for patterns that can be optimized */
4941                                                         
4942                                                         genc16bit2lit(left,lit,0);
4943                                                         lit >>= 16;
4944                                                         if(lit) {
4945                                                                 genSkipz(ifx,IC_TRUE(ifx) == NULL);
4946                                                                 //genSkip(ifx,'z');
4947                                                                 genc16bit2lit(left,lit,2);
4948                                                         } else {
4949                                                                 emitpcode(POC_IORFW,popGet(AOP(left),2));
4950                                                                 emitpcode(POC_IORFW,popGet(AOP(left),3));
4951                                                                 
4952                                                         }
4953                                                         
4954                                                 }
4955                                                 
4956                                                 genSkip(ifx,'z');
4957                                 }
4958                                 
4959                                 ifx->generated = 1;
4960                                 goto release ;
4961                                 
4962                                 
4963                         } else if(AOP_TYPE(right) == AOP_CRY ) {
4964                                 /* we know the left is not a bit, but that the right is */
4965                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4966                                 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
4967                                         popGet(AOP(right),offset));
4968                                 emitpcode(POC_XORLW,popGetLit(1));
4969                                 
4970                                 /* if the two are equal, then W will be 0 and the Z bit is set
4971                                 * we could test Z now, or go ahead and check the high order bytes if
4972                                 * the variable we're comparing is larger than a byte. */
4973                                 
4974                                 while(--size)
4975                                         emitpcode(POC_IORFW,popGet(AOP(left),offset));
4976                                 
4977                                 if ( IC_TRUE(ifx) ) {
4978                                         emitSKPNZ;
4979                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
4980                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4981                                 } else {
4982                                         emitSKPZ;
4983                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
4984                                         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4985                                 }
4986                                 
4987                         } else {
4988                                 /* They're both variables that are larger than bits */
4989                                 int s = size;
4990                                 
4991                                 tlbl = newiTempLabel(NULL);
4992                                 
4993                                 while(size--) {
4994                                         mov2w (AOP(right),offset); /* right might be litLike() */
4995                                         emitpcode(POC_XORFW,popGet(AOP(left),offset));
4996                                         
4997                                         if ( IC_TRUE(ifx) ) {
4998                                                 if(size) {
4999                                                         emitSKPZ;
5000                                                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5001                                                         pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5002                                                 } else {
5003                                                         emitSKPNZ;
5004                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5005                                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5006                                                 }
5007                                         } else {
5008                                                 emitSKPZ;
5009                                                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5010                                                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5011                                         }
5012                                         offset++;
5013                                 }
5014                                 if(s>1 && IC_TRUE(ifx)) {
5015                                         emitpLabel(tlbl->key);
5016                                         pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5017                                 }
5018                         }
5019                 }
5020                 /* mark the icode as generated */
5021                 ifx->generated = 1;
5022                 goto release ;
5023         }
5024   
5025   /* if they are both bit variables */
5026   if (AOP_TYPE(left) == AOP_CRY &&
5027           ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5028           if(AOP_TYPE(right) == AOP_LIT){
5029                   unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5030                   if(lit == 0L){
5031                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5032                           pic14_emitcode("cpl","c");
5033                   } else if(lit == 1L) {
5034                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5035                   } else {
5036                           pic14_emitcode("clr","c");
5037                   }
5038                   /* AOP_TYPE(right) == AOP_CRY */
5039           } else {
5040                   symbol *lbl = newiTempLabel(NULL);
5041                   pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5042                   pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5043                   pic14_emitcode("cpl","c");
5044                   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5045           }
5046           /* c = 1 if egal */
5047           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5048                   pic14_outBitC(result);
5049                   goto release ;
5050           }
5051           if (ifx) {
5052                   genIfxJump (ifx,"c");
5053                   goto release ;
5054           }
5055           /* if the result is used in an arithmetic operation
5056           then put the result in place */
5057           pic14_outBitC(result);
5058   } else {
5059           
5060           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5061           gencjne(left,right,result,ifx);
5062           /*
5063           if(ifx) 
5064           gencjne(left,right,newiTempLabel(NULL));
5065           else {
5066           if(IC_TRUE(ifx)->key)
5067           gencjne(left,right,IC_TRUE(ifx)->key);
5068           else
5069           gencjne(left,right,IC_FALSE(ifx)->key);
5070           ifx->generated = 1;
5071           goto release ;
5072           }
5073           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5074           aopPut(AOP(result),"a",0);
5075           goto release ;
5076           }
5077           
5078                 if (ifx) {
5079                 genIfxJump (ifx,"a");
5080                 goto release ;
5081                 }
5082           */
5083           /* if the result is used in an arithmetic operation
5084           then put the result in place */
5085           /*
5086           if (AOP_TYPE(result) != AOP_CRY) 
5087           pic14_outAcc(result);
5088           */
5089           /* leave the result in acc */
5090   }
5091   
5092 release:
5093   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5094   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5095   freeAsmop(result,NULL,ic,TRUE);
5096 }
5097
5098 /*-----------------------------------------------------------------*/
5099 /* ifxForOp - returns the icode containing the ifx for operand     */
5100 /*-----------------------------------------------------------------*/
5101 static iCode *ifxForOp ( operand *op, iCode *ic )
5102 {
5103         FENTRY;
5104         /* if true symbol then needs to be assigned */
5105         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5106         if (IS_TRUE_SYMOP(op))
5107                 return NULL ;
5108         
5109         /* if this has register type condition and
5110         the next instruction is ifx with the same operand
5111         and live to of the operand is upto the ifx only then */
5112         if (ic->next &&
5113                 ic->next->op == IFX &&
5114                 IC_COND(ic->next)->key == op->key &&
5115                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5116                 return ic->next;
5117         
5118         if (ic->next &&
5119                 ic->next->op == IFX &&
5120                 IC_COND(ic->next)->key == op->key) {
5121                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5122                 return ic->next;
5123         }
5124         
5125         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5126         if (ic->next &&
5127                 ic->next->op == IFX)
5128                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5129         
5130         if (ic->next &&
5131                 ic->next->op == IFX &&
5132                 IC_COND(ic->next)->key == op->key) {
5133                 DEBUGpic14_emitcode ("; "," key is okay");
5134                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5135                         OP_SYMBOL(op)->liveTo,
5136                         ic->next->seq);
5137         }
5138         
5139         
5140         return NULL;
5141 }
5142 /*-----------------------------------------------------------------*/
5143 /* genAndOp - for && operation                                     */
5144 /*-----------------------------------------------------------------*/
5145 static void genAndOp (iCode *ic)
5146 {
5147         operand *left,*right, *result;
5148         /*     symbol *tlbl; */
5149         
5150         FENTRY;
5151         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5152         /* note here that && operations that are in an
5153         if statement are taken away by backPatchLabels
5154         only those used in arthmetic operations remain */
5155         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5156         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5157         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5158         
5159         DEBUGpic14_AopType(__LINE__,left,right,result);
5160         
5161         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5162         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5163         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5164         
5165         /* if both are bit variables */
5166         /*     if (AOP_TYPE(left) == AOP_CRY && */
5167         /*         AOP_TYPE(right) == AOP_CRY ) { */
5168         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5169         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5170         /*         pic14_outBitC(result); */
5171         /*     } else { */
5172         /*         tlbl = newiTempLabel(NULL); */
5173         /*         pic14_toBoolean(left);     */
5174         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5175         /*         pic14_toBoolean(right); */
5176         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5177         /*         pic14_outBitAcc(result); */
5178         /*     } */
5179         
5180         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5181         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5182         freeAsmop(result,NULL,ic,TRUE);
5183 }
5184
5185
5186 /*-----------------------------------------------------------------*/
5187 /* genOrOp - for || operation                                      */
5188 /*-----------------------------------------------------------------*/
5189 /*
5190 tsd pic port -
5191 modified this code, but it doesn't appear to ever get called
5192 */
5193
5194 static void genOrOp (iCode *ic)
5195 {
5196         operand *left,*right, *result;
5197         symbol *tlbl;
5198         
5199         /* note here that || operations that are in an
5200         if statement are taken away by backPatchLabels
5201         only those used in arthmetic operations remain */
5202         FENTRY;
5203         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5204         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5205         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5206         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5207         
5208         DEBUGpic14_AopType(__LINE__,left,right,result);
5209         
5210         /* if both are bit variables */
5211         if (AOP_TYPE(left) == AOP_CRY &&
5212                 AOP_TYPE(right) == AOP_CRY ) {
5213                 pic14_emitcode("clrc","");
5214                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5215                         AOP(left)->aopu.aop_dir,
5216                         AOP(left)->aopu.aop_dir);
5217                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5218                         AOP(right)->aopu.aop_dir,
5219                         AOP(right)->aopu.aop_dir);
5220                 pic14_emitcode("setc","");
5221                 
5222         } else {
5223                 tlbl = newiTempLabel(NULL);
5224                 pic14_toBoolean(left);
5225                 emitSKPZ;
5226                 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5227                 pic14_toBoolean(right);
5228                 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5229                 
5230                 pic14_outBitAcc(result);
5231         }
5232         
5233         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5234         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5235         freeAsmop(result,NULL,ic,TRUE);            
5236 }
5237
5238 /*-----------------------------------------------------------------*/
5239 /* isLiteralBit - test if lit == 2^n                               */
5240 /*-----------------------------------------------------------------*/
5241 static int isLiteralBit(unsigned long lit)
5242 {
5243         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5244                 0x100L,0x200L,0x400L,0x800L,
5245                 0x1000L,0x2000L,0x4000L,0x8000L,
5246                 0x10000L,0x20000L,0x40000L,0x80000L,
5247                 0x100000L,0x200000L,0x400000L,0x800000L,
5248                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5249                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5250         int idx;
5251         
5252         FENTRY;
5253         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5254         for(idx = 0; idx < 32; idx++)
5255                 if(lit == pw[idx])
5256                         return idx+1;
5257                 return 0;
5258 }
5259
5260 /*-----------------------------------------------------------------*/
5261 /* continueIfTrue -                                                */
5262 /*-----------------------------------------------------------------*/
5263 static void continueIfTrue (iCode *ic)
5264 {
5265         FENTRY;
5266         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5267         if(IC_TRUE(ic))
5268                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5269         ic->generated = 1;
5270 }
5271
5272 /*-----------------------------------------------------------------*/
5273 /* jmpIfTrue -                                                     */
5274 /*-----------------------------------------------------------------*/
5275 static void jumpIfTrue (iCode *ic)
5276 {
5277         FENTRY;
5278         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5279         if(!IC_TRUE(ic))
5280                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5281         ic->generated = 1;
5282 }
5283
5284 /*-----------------------------------------------------------------*/
5285 /* jmpTrueOrFalse -                                                */
5286 /*-----------------------------------------------------------------*/
5287 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5288 {
5289         FENTRY;
5290         // ugly but optimized by peephole
5291         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5292         if(IC_TRUE(ic)){
5293                 symbol *nlbl = newiTempLabel(NULL);
5294                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5295                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5296                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5297                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5298         }
5299         else{
5300                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5301                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5302         }
5303         ic->generated = 1;
5304 }
5305
5306 /*-----------------------------------------------------------------*/
5307 /* genAnd  - code for and                                          */
5308 /*-----------------------------------------------------------------*/
5309 static void genAnd (iCode *ic, iCode *ifx)
5310 {
5311         operand *left, *right, *result;
5312         int size, offset=0;  
5313         unsigned long lit = 0L;
5314         int bytelit = 0;
5315         resolvedIfx rIfx;
5316         
5317         FENTRY;
5318         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5319         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5320         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5321         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5322         
5323         resolveIfx(&rIfx,ifx);
5324         
5325         /* if left is a literal & right is not then exchange them */
5326         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5327                 AOP_NEEDSACC(left)) {
5328                 operand *tmp = right ;
5329                 right = left;
5330                 left = tmp;
5331         }
5332         
5333         /* if result = right then exchange them */
5334         if(pic14_sameRegs(AOP(result),AOP(right))){
5335                 operand *tmp = right ;
5336                 right = left;
5337                 left = tmp;
5338         }
5339         
5340         /* if right is bit then exchange them */
5341         if (AOP_TYPE(right) == AOP_CRY &&
5342                 AOP_TYPE(left) != AOP_CRY){
5343                 operand *tmp = right ;
5344                 right = left;
5345                 left = tmp;
5346         }
5347         if(AOP_TYPE(right) == AOP_LIT)
5348                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5349         
5350         size = AOP_SIZE(result);
5351         
5352         DEBUGpic14_AopType(__LINE__,left,right,result);
5353         
5354         // if(bit & yy)
5355         // result = bit & yy;
5356         if (AOP_TYPE(left) == AOP_CRY){
5357                 // c = bit & literal;
5358                 if(AOP_TYPE(right) == AOP_LIT){
5359                         if(lit & 1) {
5360                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5361                                         // no change
5362                                         goto release;
5363                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5364                         } else {
5365                                 // bit(result) = 0;
5366                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5367                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5368                                         goto release;
5369                                 }
5370                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5371                                         jumpIfTrue(ifx);
5372                                         goto release;
5373                                 }
5374                                 pic14_emitcode("clr","c");
5375                         }
5376                 } else {
5377                         if (AOP_TYPE(right) == AOP_CRY){
5378                                 // c = bit & bit;
5379                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5380                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5381                         } else {
5382                                 // c = bit & val;
5383                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5384                                 // c = lsb
5385                                 pic14_emitcode("rrc","a");
5386                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5387                         }
5388                 }
5389                 // bit = c
5390                 // val = c
5391                 if(size)
5392                         pic14_outBitC(result);
5393                 // if(bit & ...)
5394                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5395                         genIfxJump(ifx, "c");           
5396                 goto release ;
5397         }
5398         
5399         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5400         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5401         if((AOP_TYPE(right) == AOP_LIT) &&
5402                 (AOP_TYPE(result) == AOP_CRY) &&
5403                 (AOP_TYPE(left) != AOP_CRY)){
5404                 int posbit = isLiteralBit(lit);
5405                 /* left &  2^n */
5406                 if(posbit){
5407                         posbit--;
5408                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5409                         // bit = left & 2^n
5410                         if(size)
5411                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5412                         // if(left &  2^n)
5413                         else{
5414                                 if(ifx){
5415                                         int offset = 0;
5416                                         while (posbit > 7) {
5417                                                 posbit -= 8;
5418                                                 offset++;
5419                                         }
5420                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5421                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5422                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5423                                         
5424                                         ifx->generated = 1;
5425                                 }
5426                                 goto release;
5427                         }
5428                 } else {
5429                         symbol *tlbl = newiTempLabel(NULL);
5430                         int sizel = AOP_SIZE(left);
5431                         if(size)
5432                                 pic14_emitcode("setb","c");
5433                         while(sizel--){
5434                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5435                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5436                                         // byte ==  2^n ?
5437                                         if((posbit = isLiteralBit(bytelit)) != 0)
5438                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5439                                         else{
5440                                                 if(bytelit != 0x0FFL)
5441                                                         pic14_emitcode("anl","a,%s",
5442                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5443                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5444                                         }
5445                                 }
5446                                 offset++;
5447                         }
5448                         // bit = left & literal
5449                         if(size){
5450                                 pic14_emitcode("clr","c");
5451                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5452                         }
5453                         // if(left & literal)
5454                         else{
5455                                 if(ifx)
5456                                         jmpTrueOrFalse(ifx, tlbl);
5457                                 goto release ;
5458                         }
5459                 }
5460                 pic14_outBitC(result);
5461                 goto release ;
5462         }
5463         
5464         /* if left is same as result */
5465         if(pic14_sameRegs(AOP(result),AOP(left))){
5466                 int know_W = -1;
5467                 for(;size--; offset++,lit>>=8) {
5468                         if(AOP_TYPE(right) == AOP_LIT){
5469                                 switch(lit & 0xff) {
5470                                 case 0x00:
5471                                         /*  and'ing with 0 has clears the result */
5472                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5473                                         break;
5474                                 case 0xff:
5475                                         /* and'ing with 0xff is a nop when the result and left are the same */
5476                                         break;
5477                                         
5478                                 default:
5479                                         {
5480                                                 int p = my_powof2( (~lit) & 0xff );
5481                                                 if(p>=0) {
5482                                                         /* only one bit is set in the literal, so use a bcf instruction */
5483                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5484                                                         
5485                                                 } else {
5486                                                         if(know_W != (int)(lit&0xff))
5487                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5488                                                         know_W = lit &0xff;
5489                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5490                                                 }
5491                                         }    
5492                                 }
5493                         } else {
5494                                 if (AOP_TYPE(left) == AOP_ACC) {
5495                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5496                                 } else {        
5497                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5498                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5499                                         
5500                                 }
5501                         }
5502                 }
5503                 
5504         } else {
5505                 // left & result in different registers
5506                 if(AOP_TYPE(result) == AOP_CRY){
5507                         // result = bit
5508                         // if(size), result in bit
5509                         // if(!size && ifx), conditional oper: if(left & right)
5510                         symbol *tlbl = newiTempLabel(NULL);
5511                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5512                         if(size)
5513                                 pic14_emitcode("setb","c");
5514                         while(sizer--){
5515                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5516                                 pic14_emitcode("anl","a,%s",
5517                                         aopGet(AOP(left),offset,FALSE,FALSE));
5518                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5519                                 offset++;
5520                         }
5521                         if(size){
5522                                 CLRC;
5523                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5524                                 pic14_outBitC(result);
5525                         } else if(ifx)
5526                                 jmpTrueOrFalse(ifx, tlbl);
5527                 } else {
5528                         for(;(size--);offset++) {
5529                                 // normal case
5530                                 // result = left & right
5531                                 if(AOP_TYPE(right) == AOP_LIT){
5532                                         int t = (lit >> (offset*8)) & 0x0FFL;
5533                                         switch(t) { 
5534                                         case 0x00:
5535                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5536                                                 break;
5537                                         case 0xff:
5538                                                 if(AOP_TYPE(left) != AOP_ACC) {
5539                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5540                                                 }
5541                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5542                                                 break;
5543                                         default:
5544                                                 if(AOP_TYPE(left) == AOP_ACC) {
5545                                                         emitpcode(POC_ANDLW, popGetLit(t));
5546                                                 } else {
5547                                                         emitpcode(POC_MOVLW, popGetLit(t));
5548                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5549                                                 }
5550                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5551                                         }
5552                                         continue;
5553                                 }
5554                                 
5555                                 if (AOP_TYPE(left) == AOP_ACC) {
5556                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5557                                 } else {
5558                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5559                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5560                                 }
5561                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5562                         }
5563                 }
5564         }
5565         
5566 release :
5567         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5568         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5569         freeAsmop(result,NULL,ic,TRUE);     
5570 }
5571
5572 /*-----------------------------------------------------------------*/
5573 /* genOr  - code for or                                            */
5574 /*-----------------------------------------------------------------*/
5575 static void genOr (iCode *ic, iCode *ifx)
5576 {
5577         operand *left, *right, *result;
5578         int size, offset=0;
5579         unsigned long lit = 0L;
5580         
5581         FENTRY;
5582         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5583         
5584         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5585         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5586         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5587         
5588         DEBUGpic14_AopType(__LINE__,left,right,result);
5589         
5590         /* if left is a literal & right is not then exchange them */
5591         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5592                 AOP_NEEDSACC(left)) {
5593                 operand *tmp = right ;
5594                 right = left;
5595                 left = tmp;
5596         }
5597         
5598         /* if result = right then exchange them */
5599         if(pic14_sameRegs(AOP(result),AOP(right))){
5600                 operand *tmp = right ;
5601                 right = left;
5602                 left = tmp;
5603         }
5604         
5605         /* if right is bit then exchange them */
5606         if (AOP_TYPE(right) == AOP_CRY &&
5607                 AOP_TYPE(left) != AOP_CRY){
5608                 operand *tmp = right ;
5609                 right = left;
5610                 left = tmp;
5611         }
5612         
5613         DEBUGpic14_AopType(__LINE__,left,right,result);
5614         
5615         if(AOP_TYPE(right) == AOP_LIT)
5616                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5617         
5618         size = AOP_SIZE(result);
5619         
5620         // if(bit | yy)
5621         // xx = bit | yy;
5622         if (AOP_TYPE(left) == AOP_CRY){
5623                 if(AOP_TYPE(right) == AOP_LIT){
5624                         // c = bit & literal;
5625                         if(lit){
5626                                 // lit != 0 => result = 1
5627                                 if(AOP_TYPE(result) == AOP_CRY){
5628                                         if(size)
5629                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5630                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5631                                         //   AOP(result)->aopu.aop_dir,
5632                                         //   AOP(result)->aopu.aop_dir);
5633                                         else if(ifx)
5634                                                 continueIfTrue(ifx);
5635                                         goto release;
5636                                 }
5637                         } else {
5638                                 // lit == 0 => result = left
5639                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5640                                         goto release;
5641                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5642                         }
5643                 } else {
5644                         if (AOP_TYPE(right) == AOP_CRY){
5645                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5646                                         // c = bit | bit;
5647                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5648                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5649                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5650                                         
5651                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5652                                                 AOP(result)->aopu.aop_dir,
5653                                                 AOP(result)->aopu.aop_dir);
5654                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5655                                                 AOP(right)->aopu.aop_dir,
5656                                                 AOP(right)->aopu.aop_dir);
5657                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5658                                                 AOP(result)->aopu.aop_dir,
5659                                                 AOP(result)->aopu.aop_dir);
5660                                 } else {
5661                                         if( AOP_TYPE(result) == AOP_ACC) {
5662                                                 emitpcode(POC_MOVLW, popGetLit(0));
5663                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5664                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5665                                                 emitpcode(POC_MOVLW, popGetLit(1));
5666                                                 
5667                                         } else {
5668                                                 
5669                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5670                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5671                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5672                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5673                                                 
5674                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5675                                                         AOP(result)->aopu.aop_dir,
5676                                                         AOP(result)->aopu.aop_dir);
5677                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5678                                                         AOP(right)->aopu.aop_dir,
5679                                                         AOP(right)->aopu.aop_dir);
5680                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5681                                                         AOP(left)->aopu.aop_dir,
5682                                                         AOP(left)->aopu.aop_dir);
5683                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5684                                                         AOP(result)->aopu.aop_dir,
5685                                                         AOP(result)->aopu.aop_dir);
5686                                         }
5687                                 }
5688                         } else {
5689                                 // c = bit | val;
5690                                 symbol *tlbl = newiTempLabel(NULL);
5691                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5692                                 
5693                                 
5694                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5695                                 if( AOP_TYPE(right) == AOP_ACC) {
5696                                         emitpcode(POC_IORLW, popGetLit(0));
5697                                         emitSKPNZ;
5698                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5699                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5700                                 }
5701                                 
5702                                 
5703                                 
5704                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5705                                         pic14_emitcode(";XXX setb","c");
5706                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5707                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5708                                 pic14_toBoolean(right);
5709                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5710                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5711                                         jmpTrueOrFalse(ifx, tlbl);
5712                                         goto release;
5713                                 } else {
5714                                         CLRC;
5715                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5716                                 }
5717                         }
5718                 }
5719                 // bit = c
5720                 // val = c
5721                 if(size)
5722                         pic14_outBitC(result);
5723                 // if(bit | ...)
5724                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5725                         genIfxJump(ifx, "c");           
5726                 goto release ;
5727         }
5728
5729         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5730         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5731         if((AOP_TYPE(right) == AOP_LIT) &&
5732           (AOP_TYPE(result) == AOP_CRY) &&
5733           (AOP_TYPE(left) != AOP_CRY)){
5734                 if(lit){
5735                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5736                         // result = 1
5737                         if(size)
5738                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5739                         else 
5740                                 continueIfTrue(ifx);
5741                         goto release;
5742                 } else {
5743                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5744                         // lit = 0, result = boolean(left)
5745                         if(size)
5746                                 pic14_emitcode(";XXX setb","c");
5747                         pic14_toBoolean(right);
5748                         if(size){
5749                                 symbol *tlbl = newiTempLabel(NULL);
5750                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5751                                 CLRC;
5752                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5753                         } else {
5754                                 genIfxJump (ifx,"a");
5755                                 goto release;
5756                         }
5757                 }
5758                 pic14_outBitC(result);
5759                 goto release ;
5760         }
5761
5762         /* if left is same as result */
5763         if(pic14_sameRegs(AOP(result),AOP(left))){
5764                 int know_W = -1;
5765                 for(;size--; offset++,lit>>=8) {
5766                         if(AOP_TYPE(right) == AOP_LIT){
5767                                 if((lit & 0xff) == 0)
5768                                         /*  or'ing with 0 has no effect */
5769                                         continue;
5770                                 else {
5771                                         int p = my_powof2(lit & 0xff);
5772                                         if(p>=0) {
5773                                                 /* only one bit is set in the literal, so use a bsf instruction */
5774                                                 emitpcode(POC_BSF,
5775                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5776                                         } else {
5777                                                 if(know_W != (int)(lit & 0xff))
5778                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5779                                                 know_W = lit & 0xff;
5780                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5781                                         }
5782                                         
5783                                 }
5784                         } else {
5785                                 if (AOP_TYPE(left) == AOP_ACC) {
5786                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5787                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5788                                 } else {        
5789                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5790                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5791                                         
5792                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5793                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5794                                         
5795                                 }
5796                         }
5797                 }
5798         } else {
5799                 // left & result in different registers
5800                 if(AOP_TYPE(result) == AOP_CRY){
5801                         // result = bit
5802                         // if(size), result in bit
5803                         // if(!size && ifx), conditional oper: if(left | right)
5804                         symbol *tlbl = newiTempLabel(NULL);
5805                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5806                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5807                         
5808                         
5809                         if(size)
5810                                 pic14_emitcode(";XXX setb","c");
5811                         while(sizer--){
5812                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5813                                 pic14_emitcode(";XXX orl","a,%s",
5814                                         aopGet(AOP(left),offset,FALSE,FALSE));
5815                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5816                                 offset++;
5817                         }
5818                         if(size){
5819                                 CLRC;
5820                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5821                                 pic14_outBitC(result);
5822                         } else if(ifx)
5823                                 jmpTrueOrFalse(ifx, tlbl);
5824                 } else for(;(size--);offset++){
5825                         // normal case
5826                         // result = left | right
5827                         if(AOP_TYPE(right) == AOP_LIT){
5828                                 int t = (lit >> (offset*8)) & 0x0FFL;
5829                                 switch(t) { 
5830                                 case 0x00:
5831                                         if (AOP_TYPE(left) != AOP_ACC) {
5832                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
5833                                         }
5834                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5835                                         
5836                                         break;
5837                                 default:
5838                                         if (AOP_TYPE(left) == AOP_ACC) {
5839                                                 emitpcode(POC_IORLW,  popGetLit(t));
5840                                         } else {
5841                                                 emitpcode(POC_MOVLW,  popGetLit(t));
5842                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
5843                                         }
5844                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
5845                                 }
5846                                 continue;
5847                         }
5848                         
5849                         // faster than result <- left, anl result,right
5850                         // and better if result is SFR
5851                         if (AOP_TYPE(left) == AOP_ACC) {
5852                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
5853                         } else {
5854                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5855                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
5856                         }
5857                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
5858                 }
5859         }
5860
5861 release :
5862         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5863         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5864         freeAsmop(result,NULL,ic,TRUE);     
5865 }
5866
5867 /*-----------------------------------------------------------------*/
5868 /* genXor - code for xclusive or                                   */
5869 /*-----------------------------------------------------------------*/
5870 static void genXor (iCode *ic, iCode *ifx)
5871 {
5872         operand *left, *right, *result;
5873         int size, offset=0;
5874         unsigned long lit = 0L;
5875         
5876         FENTRY;
5877         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5878         
5879         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5880         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5881         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5882         
5883         /* if left is a literal & right is not ||
5884         if left needs acc & right does not */
5885         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5886                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
5887                 operand *tmp = right ;
5888                 right = left;
5889                 left = tmp;
5890         }
5891         
5892         /* if result = right then exchange them */
5893         if(pic14_sameRegs(AOP(result),AOP(right))){
5894                 operand *tmp = right ;
5895                 right = left;
5896                 left = tmp;
5897         }
5898         
5899         /* if right is bit then exchange them */
5900         if (AOP_TYPE(right) == AOP_CRY &&
5901                 AOP_TYPE(left) != AOP_CRY){
5902                 operand *tmp = right ;
5903                 right = left;
5904                 left = tmp;
5905         }
5906         if(AOP_TYPE(right) == AOP_LIT)
5907                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5908         
5909         size = AOP_SIZE(result);
5910         
5911         // if(bit ^ yy)
5912         // xx = bit ^ yy;
5913         if (AOP_TYPE(left) == AOP_CRY){
5914                 if(AOP_TYPE(right) == AOP_LIT){
5915                         // c = bit & literal;
5916                         if(lit>>1){
5917                                 // lit>>1  != 0 => result = 1
5918                                 if(AOP_TYPE(result) == AOP_CRY){
5919                                         if(size)
5920                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
5921                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
5922                                         else if(ifx)
5923                                                 continueIfTrue(ifx);
5924                                         goto release;
5925                                 }
5926                                 pic14_emitcode("setb","c");
5927                         } else{
5928                                 // lit == (0 or 1)
5929                                 if(lit == 0){
5930                                         // lit == 0, result = left
5931                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
5932                                                 goto release;
5933                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5934                                 } else{
5935                                         // lit == 1, result = not(left)
5936                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
5937                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
5938                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
5939                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
5940                                                 goto release;
5941                                         } else {
5942                                                 assert ( !"incomplete genXor" );
5943                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5944                                                 pic14_emitcode("cpl","c");
5945                                         }
5946                                 }
5947                         }
5948                         
5949                 } else {
5950                         // right != literal
5951                         symbol *tlbl = newiTempLabel(NULL);
5952                         if (AOP_TYPE(right) == AOP_CRY){
5953                                 // c = bit ^ bit;
5954                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5955                         }
5956                         else{
5957                                 int sizer = AOP_SIZE(right);
5958                                 // c = bit ^ val
5959                                 // if val>>1 != 0, result = 1
5960                                 pic14_emitcode("setb","c");
5961                                 while(sizer){
5962                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
5963                                         if(sizer == 1)
5964                                                 // test the msb of the lsb
5965                                                 pic14_emitcode("anl","a,#0xfe");
5966                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5967                                         sizer--;
5968                                 }
5969                                 // val = (0,1)
5970                                 pic14_emitcode("rrc","a");
5971                         }
5972                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
5973                         pic14_emitcode("cpl","c");
5974                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
5975                 }
5976                 // bit = c
5977                 // val = c
5978                 if(size)
5979                         pic14_outBitC(result);
5980                 // if(bit | ...)
5981                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5982                         genIfxJump(ifx, "c");           
5983                 goto release ;
5984         }
5985         
5986         if(pic14_sameRegs(AOP(result),AOP(left))){
5987                 /* if left is same as result */
5988                 for(;size--; offset++) {
5989                         if(AOP_TYPE(right) == AOP_LIT){
5990                                 int t  = (lit >> (offset*8)) & 0x0FFL;
5991                                 if(t == 0x00L)
5992                                         continue;
5993                                 else
5994                                         if (IS_AOP_PREG(left)) {
5995                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5996                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
5997                                                 aopPut(AOP(result),"a",offset);
5998                                         } else {
5999                                                 emitpcode(POC_MOVLW, popGetLit(t));
6000                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6001                                                 pic14_emitcode("xrl","%s,%s",
6002                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6003                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6004                                         }
6005                         } else {
6006                                 if (AOP_TYPE(left) == AOP_ACC)
6007                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6008                                 else {
6009                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6010                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6011                                         /*
6012                                         if (IS_AOP_PREG(left)) {
6013                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6014                                         aopPut(AOP(result),"a",offset);
6015                                         } else
6016                                         pic14_emitcode("xrl","%s,a",
6017                                         aopGet(AOP(left),offset,FALSE,TRUE));
6018                                         */
6019                                 }
6020                         }
6021                 }
6022         } else {
6023                 // left & result in different registers
6024                 if(AOP_TYPE(result) == AOP_CRY){
6025                         // result = bit
6026                         // if(size), result in bit
6027                         // if(!size && ifx), conditional oper: if(left ^ right)
6028                         symbol *tlbl = newiTempLabel(NULL);
6029                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6030                         if(size)
6031                                 pic14_emitcode("setb","c");
6032                         while(sizer--){
6033                                 if((AOP_TYPE(right) == AOP_LIT) &&
6034                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6035                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6036                                 } else {
6037                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6038                                         pic14_emitcode("xrl","a,%s",
6039                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6040                                 }
6041                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6042                                 offset++;
6043                         }
6044                         if(size){
6045                                 CLRC;
6046                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6047                                 pic14_outBitC(result);
6048                         } else if(ifx)
6049                                 jmpTrueOrFalse(ifx, tlbl);
6050                 } else for(;(size--);offset++){
6051                         // normal case
6052                         // result = left & right
6053                         if(AOP_TYPE(right) == AOP_LIT){
6054                                 int t = (lit >> (offset*8)) & 0x0FFL;
6055                                 switch(t) { 
6056                                 case 0x00:
6057                                         if (AOP_TYPE(left) != AOP_ACC) {
6058                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6059                                         }
6060                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6061                                         pic14_emitcode("movf","%s,w",
6062                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6063                                         pic14_emitcode("movwf","%s",
6064                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6065                                         break;
6066                                 case 0xff:
6067                                         if (AOP_TYPE(left) == AOP_ACC) {
6068                                                 emitpcode(POC_XORLW, popGetLit(t));
6069                                         } else {
6070                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6071                                         }
6072                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6073                                         break;
6074                                 default:
6075                                         if (AOP_TYPE(left) == AOP_ACC) {
6076                                                 emitpcode(POC_XORLW, popGetLit(t));
6077                                         } else {
6078                                                 emitpcode(POC_MOVLW, popGetLit(t));
6079                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6080                                         }
6081                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6082                                         pic14_emitcode("movlw","0x%x",t);
6083                                         pic14_emitcode("xorwf","%s,w",
6084                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6085                                         pic14_emitcode("movwf","%s",
6086                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6087                                         
6088                                 }
6089                                 continue;
6090                         }
6091                         
6092                         // faster than result <- left, anl result,right
6093                         // and better if result is SFR
6094                         if (AOP_TYPE(left) == AOP_ACC) {
6095                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6096                         } else {
6097                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6098                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6099                         }
6100                         if ( AOP_TYPE(result) != AOP_ACC){
6101                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6102                         }
6103                 }
6104         }
6105         
6106 release :
6107         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6108         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6109         freeAsmop(result,NULL,ic,TRUE);     
6110 }
6111
6112 /*-----------------------------------------------------------------*/
6113 /* genInline - write the inline code out                           */
6114 /*-----------------------------------------------------------------*/
6115 static void genInline (iCode *ic)
6116 {
6117   char *buffer, *bp, *bp1;
6118
6119   FENTRY;
6120   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6121
6122   _G.inLine += (!options.asmpeep);
6123
6124   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6125   strcpy(buffer,IC_INLINE(ic));
6126
6127   /* emit each line as a code */
6128   while (*bp) {
6129     if (*bp == '\n') {
6130       *bp++ = '\0';
6131       
6132       if(*bp1)
6133         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6134       bp1 = bp;
6135     } else {
6136       if (*bp == ':') {
6137         bp++;
6138         *bp = '\0';
6139         bp++;
6140
6141         /* print label, use this special format with NULL directive
6142          * to denote that the argument should not be indented with tab */
6143         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6144
6145         bp1 = bp;
6146       } else
6147         bp++;
6148     }
6149   }
6150   if ((bp1 != bp) && *bp1)
6151     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6152
6153   Safe_free(buffer);
6154
6155   _G.inLine -= (!options.asmpeep);
6156 }
6157
6158 /*-----------------------------------------------------------------*/
6159 /* genRRC - rotate right with carry                                */
6160 /*-----------------------------------------------------------------*/
6161 static void genRRC (iCode *ic)
6162 {
6163         operand *left , *result ;
6164         int size, offset = 0, same;
6165         
6166         FENTRY;
6167         /* rotate right with carry */
6168         left = IC_LEFT(ic);
6169         result=IC_RESULT(ic);
6170         aopOp (left,ic,FALSE);
6171         aopOp (result,ic,FALSE);
6172         
6173         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6174         
6175         same = pic14_sameRegs(AOP(result),AOP(left));
6176         
6177         size = AOP_SIZE(result);    
6178         
6179         /* get the lsb and put it into the carry */
6180         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6181         
6182         offset = 0 ;
6183         
6184         while(size--) {
6185                 
6186                 if(same) {
6187                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6188                 } else {
6189                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6190                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6191                 }
6192                 
6193                 offset++;
6194         }
6195         
6196         freeAsmop(left,NULL,ic,TRUE);
6197         freeAsmop(result,NULL,ic,TRUE);
6198 }
6199
6200 /*-----------------------------------------------------------------*/
6201 /* genRLC - generate code for rotate left with carry               */
6202 /*-----------------------------------------------------------------*/
6203 static void genRLC (iCode *ic)
6204 {    
6205         operand *left , *result ;
6206         int size, offset = 0;
6207         int same;
6208         
6209         FENTRY;
6210         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6211         /* rotate right with carry */
6212         left = IC_LEFT(ic);
6213         result=IC_RESULT(ic);
6214         aopOp (left,ic,FALSE);
6215         aopOp (result,ic,FALSE);
6216         
6217         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6218         
6219         same = pic14_sameRegs(AOP(result),AOP(left));
6220         
6221         /* move it to the result */
6222         size = AOP_SIZE(result);    
6223         
6224         /* get the msb and put it into the carry */
6225         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6226         
6227         offset = 0 ;
6228         
6229         while(size--) {
6230                 
6231                 if(same) {
6232                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6233                 } else {
6234                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6235                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6236                 }
6237                 
6238                 offset++;
6239         }
6240         
6241         
6242         freeAsmop(left,NULL,ic,TRUE);
6243         freeAsmop(result,NULL,ic,TRUE);
6244 }
6245
6246 /*-----------------------------------------------------------------*/
6247 /* genGetHbit - generates code get highest order bit               */
6248 /*-----------------------------------------------------------------*/
6249 static void genGetHbit (iCode *ic)
6250 {
6251         operand *left, *result;
6252         left = IC_LEFT(ic);
6253         result=IC_RESULT(ic);
6254         aopOp (left,ic,FALSE);
6255         aopOp (result,ic,FALSE);
6256         
6257         FENTRY;
6258         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6259         /* get the highest order byte into a */
6260         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6261         if(AOP_TYPE(result) == AOP_CRY){
6262                 pic14_emitcode("rlc","a");
6263                 pic14_outBitC(result);
6264         }
6265         else{
6266                 pic14_emitcode("rl","a");
6267                 pic14_emitcode("anl","a,#0x01");
6268                 pic14_outAcc(result);
6269         }
6270         
6271         
6272         freeAsmop(left,NULL,ic,TRUE);
6273         freeAsmop(result,NULL,ic,TRUE);
6274 }
6275
6276 /*-----------------------------------------------------------------*/
6277 /* AccRol - rotate left accumulator by known count                 */
6278 /*-----------------------------------------------------------------*/
6279 static void AccRol (operand *op,int offset,int shCount)
6280 {
6281         FENTRY;
6282         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6283         shCount &= 0x0007;              // shCount : 0..7
6284         switch(shCount){
6285         case 0 :
6286                 break;
6287         case 1 :
6288                 pic14_emitcode("rl","a");
6289                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6290                 break;
6291         case 2 :
6292                 pic14_emitcode("rl","a");
6293                 pic14_emitcode("rl","a");
6294                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6295                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6296                 break;
6297         case 3 :
6298                 pic14_emitcode("swap","a");
6299                 pic14_emitcode("rr","a");
6300                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6301                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6302                 break;
6303         case 4 :
6304                 pic14_emitcode("swap","a");
6305                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6306                 break;
6307         case 5 :
6308                 pic14_emitcode("swap","a");
6309                 pic14_emitcode("rl","a");
6310                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6311                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6312                 break;
6313         case 6 :
6314                 pic14_emitcode("rr","a");
6315                 pic14_emitcode("rr","a");
6316                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6317                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6318                 break;
6319         case 7 :
6320                 pic14_emitcode("rr","a");
6321                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6322                 break;
6323         }
6324 }
6325
6326 /*-----------------------------------------------------------------*/
6327 /* AccLsh - left shift accumulator by known count                  */
6328 /*-----------------------------------------------------------------*/
6329 static void AccLsh (operand *op,int offset,int shCount)
6330 {
6331         FENTRY;
6332         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6333         if(shCount != 0) {
6334                 if (shCount == 1)
6335                 {
6336                         emitCLRC;
6337                         emitpcode (POC_RLF, popGet (AOP(op), 0));
6338                 } else {
6339                         /* rotate left accumulator */
6340                         AccRol(op,offset,shCount);
6341                         /* and kill the lower order bits */
6342                         emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
6343                         emitpcode (POC_ANDWF, popGet (AOP(op),0));
6344                 }
6345         }
6346 }
6347
6348 /*-----------------------------------------------------------------*/
6349 /* AccRsh - right shift accumulator by known count                 */
6350 /*-----------------------------------------------------------------*/
6351 static void AccRsh (operand *op,int offset,int shCount)
6352 {
6353         FENTRY;
6354         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6355         if(shCount != 0){
6356                 if(shCount == 1){
6357                         emitCLRC;
6358                         emitpcode (POC_RRF, popGet (AOP(op), 0));
6359                 } else {
6360                         /* rotate right accumulator */
6361                         AccRol(op,offset,8 - shCount);
6362                         /* and kill the higher order bits */
6363                         emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
6364                         emitpcode (POC_ANDWF, popGet (AOP(op),0));
6365                 }
6366         }
6367 }
6368
6369 #if 0
6370 /*-----------------------------------------------------------------*/
6371 /* AccSRsh - signed right shift accumulator by known count                 */
6372 /*-----------------------------------------------------------------*/
6373 static void AccSRsh (int shCount)
6374 {
6375         symbol *tlbl ;
6376         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6377         if(shCount != 0){
6378                 if(shCount == 1){
6379                         pic14_emitcode("mov","c,acc.7");
6380                         pic14_emitcode("rrc","a");
6381                 } else if(shCount == 2){
6382                         pic14_emitcode("mov","c,acc.7");
6383                         pic14_emitcode("rrc","a");
6384                         pic14_emitcode("mov","c,acc.7");
6385                         pic14_emitcode("rrc","a");
6386                 } else {
6387                         tlbl = newiTempLabel(NULL);
6388                         /* rotate right accumulator */
6389                         AccRol(8 - shCount);
6390                         /* and kill the higher order bits */
6391                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6392                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6393                         pic14_emitcode("orl","a,#0x%02x",
6394                                 (unsigned char)~SRMask[shCount]);
6395                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6396                 }
6397         }
6398 }
6399
6400 /*-----------------------------------------------------------------*/
6401 /* shiftR1Left2Result - shift right one byte from left to result   */
6402 /*-----------------------------------------------------------------*/
6403 static void shiftR1Left2ResultSigned (operand *left, int offl,
6404                                                                           operand *result, int offr,
6405                                                                           int shCount)
6406 {
6407         int same;
6408         
6409         FENTRY;
6410         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6411         
6412         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6413         
6414         switch(shCount) {
6415         case 1:
6416                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6417                 if(same) 
6418                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6419                 else {
6420                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6421                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6422                 }
6423                 
6424                 break;
6425         case 2:
6426                 
6427                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6428                 if(same) 
6429                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6430                 else {
6431                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6432                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6433                 }
6434                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6435                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6436                 
6437                 break;
6438                 
6439         case 3:
6440                 if(same)
6441                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6442                 else {
6443                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6444                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6445                 }
6446                 
6447                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6448                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6449                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6450                 
6451                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6452                 emitpcode(POC_IORLW, popGetLit(0xe0));
6453                 
6454                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6455                 break;
6456                 
6457         case 4:
6458                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6459                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6460                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6461                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6462                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6463                 break;
6464         case 5:
6465                 if(same) {
6466                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6467                 } else {
6468                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6469                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6470                 }
6471                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6472                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6473                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6474                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6475                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6476                 break;
6477                 
6478         case 6:
6479                 if(same) {
6480                         emitpcode(POC_MOVLW, popGetLit(0x00));
6481                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6482                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6483                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6484                         emitpcode(POC_IORLW, popGetLit(0x01));
6485                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6486                 } else {
6487                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6488                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6489                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6490                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6491                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6492                 }
6493                 break;
6494                 
6495         case 7:
6496                 if(same) {
6497                         emitpcode(POC_MOVLW, popGetLit(0x00));
6498                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6499                         emitpcode(POC_MOVLW, popGetLit(0xff));
6500                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6501                 } else {
6502                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6503                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6504                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6505                 }
6506                 
6507         default:
6508                 break;
6509         }
6510 }
6511
6512 /*-----------------------------------------------------------------*/
6513 /* shiftR1Left2Result - shift right one byte from left to result   */
6514 /*-----------------------------------------------------------------*/
6515 static void shiftR1Left2Result (operand *left, int offl,
6516                                                                 operand *result, int offr,
6517                                                                 int shCount, int sign)
6518 {
6519         int same;
6520         
6521         FENTRY;
6522         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6523         
6524         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6525         
6526         /* Copy the msb into the carry if signed. */
6527         if(sign) {
6528                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6529                 return;
6530         }
6531         
6532         
6533         
6534         switch(shCount) {
6535         case 1:
6536                 emitCLRC;
6537                 if(same) 
6538                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6539                 else {
6540                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6541                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6542                 }
6543                 break;
6544         case 2:
6545                 emitCLRC;
6546                 if(same) {
6547                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6548                 } else {
6549                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6550                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6551                 }
6552                 emitCLRC;
6553                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6554                 
6555                 break;
6556         case 3:
6557                 if(same)
6558                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6559                 else {
6560                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6561                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6562                 }
6563                 
6564                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6565                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6566                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6567                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6568                 break;
6569                 
6570         case 4:
6571                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6572                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6573                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6574                 break;
6575                 
6576         case 5:
6577                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6578                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6579                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6580                 emitCLRC;
6581                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6582                 
6583                 break;
6584         case 6:
6585                 
6586                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6587                 emitpcode(POC_ANDLW, popGetLit(0x80));
6588                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6589                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6590                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6591                 break;
6592                 
6593         case 7:
6594                 
6595                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6596                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6597                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6598                 
6599                 break;
6600                 
6601         default:
6602                 break;
6603         }
6604 }
6605
6606 /*-----------------------------------------------------------------*/
6607 /* shiftL1Left2Result - shift left one byte from left to result    */
6608 /*-----------------------------------------------------------------*/
6609 static void shiftL1Left2Result (operand *left, int offl,
6610                                                                 operand *result, int offr, int shCount)
6611 {
6612         int same;
6613         
6614         //    char *l;
6615         FENTRY;
6616         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6617         
6618         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6619         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6620         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6621         //    MOVA(l);
6622         /* shift left accumulator */
6623         //AccLsh(shCount); // don't comment out just yet...
6624         //    aopPut(AOP(result),"a",offr);
6625         
6626         switch(shCount) {
6627         case 1:
6628                 /* Shift left 1 bit position */
6629                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6630                 if(same) {
6631                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6632                 } else {
6633                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6634                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6635                 }
6636                 break;
6637         case 2:
6638                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6639                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6640                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6641                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6642                 break;
6643         case 3:
6644                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6645                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6646                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6647                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6648                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6649                 break;
6650         case 4:
6651                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6652                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6653                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6654                 break;
6655         case 5:
6656                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6657                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6658                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6659                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6660                 break;
6661         case 6:
6662                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6663                 emitpcode(POC_ANDLW, popGetLit(0x30));
6664                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6665                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6666                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6667                 break;
6668         case 7:
6669                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6670                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6671                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6672                 break;
6673                 
6674         default:
6675                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6676         }
6677         
6678 }
6679 #endif
6680
6681 /*-----------------------------------------------------------------*/
6682 /* movLeft2Result - move byte from left to result                  */
6683 /*-----------------------------------------------------------------*/
6684 static void movLeft2Result (operand *left, int offl,
6685                                                         operand *result, int offr)
6686 {
6687         char *l;
6688         FENTRY;
6689         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6690         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6691                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6692                 
6693                 if (*l == '@' && (IS_AOP_PREG(result))) {
6694                         pic14_emitcode("mov","a,%s",l);
6695                         aopPut(AOP(result),"a",offr);
6696                 } else {
6697                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6698                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6699                 }
6700         }
6701 }
6702
6703 /*-----------------------------------------------------------------*/
6704 /* shiftLeft_Left2ResultLit - shift left by known count            */
6705 /*-----------------------------------------------------------------*/
6706
6707 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6708 {
6709         int size, same, offr, i;
6710
6711         size = AOP_SIZE(left);
6712         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6713         
6714         same = pic14_sameRegs (AOP(left), AOP(result));
6715         
6716         offr = shCount / 8;
6717         shCount = shCount & 0x07;
6718
6719         size -= offr;
6720
6721         switch (shCount)
6722         {
6723         case 0: /* takes 0 or 2N cycles (for offr==0) */
6724                 if (!same || offr) {
6725                         for (i=size-1; i >= 0; i--)
6726                                 movLeft2Result (left, i, result, offr + i);
6727                 } // if
6728                 break;
6729                 
6730         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6731                 if (same && offr) {
6732                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6733                         shiftLeft_Left2ResultLit (result, result, shCount);
6734                         return; /* prevent clearing result again */
6735                 } else {
6736                         emitCLRC;
6737                         for (i=0; i < size; i++) {
6738                                 if (same && !offr) {
6739                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6740                                 } else {
6741                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6742                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6743                                 } // if
6744                         } // for
6745                 } // if (offr)
6746                 break;
6747                 
6748         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6749                 /* works in-place/with offr as well */
6750                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6751                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6752                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6753
6754                 for (i = size - 2; i >= 0; i--)
6755                 {
6756                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
6757                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6758                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6759                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
6760                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
6761                 } // for i
6762                 break;
6763                 
6764         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
6765                 /* works in-place/with offr as well */
6766                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
6767                 for (i = size-2; i >= 0; i--) {
6768                         emitpcode (POC_RRFW, popGet (AOP(left), i));
6769                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
6770                 } // for i
6771                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6772                 emitpcode (POC_RRF, popGet (AOP(result), offr));
6773                 break;
6774         
6775         default:
6776                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
6777                 shiftLeft_Left2ResultLit (result, result, 1);
6778                 return; /* prevent clearing result again */
6779                 break;
6780         } // switch
6781
6782         while (0 < offr--)
6783         {
6784                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
6785         } // while
6786 }
6787
6788 /*-----------------------------------------------------------------*/
6789 /* shiftRight_Left2ResultLit - shift right by known count          */
6790 /*-----------------------------------------------------------------*/
6791
6792 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
6793 {
6794         int size, same, offr, i;
6795
6796         size = AOP_SIZE(left);
6797         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6798         
6799         same = pic14_sameRegs (AOP(left), AOP(result));
6800         
6801         offr = shCount / 8;
6802         shCount = shCount & 0x07;
6803
6804         size -= offr;
6805
6806         if (size)
6807         {
6808                 switch (shCount)
6809                 {
6810                 case 0: /* takes 0 or 2N cycles (for offr==0) */
6811                         if (!same || offr) {
6812                                 for (i=0; i < size; i++)
6813                                         movLeft2Result (left, i + offr, result, i);
6814                         } // if
6815                         break;
6816                         
6817                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
6818                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
6819                         if (same && offr) {
6820                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
6821                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
6822                                 return; /* prevent sign-extending result again */
6823                         } else {
6824                                 emitCLRC;
6825                                 if (sign) {
6826                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
6827                                         emitSETC;
6828                                 }
6829                                 for (i = size-1; i >= 0; i--) {
6830                                         if (same && !offr) {
6831                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
6832                                         } else {
6833                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
6834                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6835                                         }
6836                                 } // for i
6837                         } // if (offr)
6838                         break;
6839                         
6840                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
6841                         /* works in-place/with offr as well */
6842                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
6843                         emitpcode (POC_ANDLW, popGetLit (0x0F));
6844                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
6845
6846                         for (i = 1; i < size; i++)
6847                         {
6848                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
6849                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6850                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6851                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
6852                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
6853                         } // for i
6854
6855                         if (sign)
6856                         {
6857                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
6858                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
6859                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
6860                         } // if
6861                         break;
6862                         
6863                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
6864                         /* works in-place/with offr as well */
6865                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
6866                         for (i = 0; i < size-1; i++) {
6867                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
6868                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
6869                         } // for i
6870                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
6871                         if (!sign) {
6872                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
6873                         } else {
6874                                 emitSKPNC;
6875                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
6876                         }
6877                         break;
6878                 
6879                 default:
6880                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
6881                         shiftRight_Left2ResultLit (result, result, 1, sign);
6882                         return; /* prevent sign extending result again */
6883                         break;
6884                 } // switch
6885         } // if
6886
6887         addSign (result, size, sign);
6888 }
6889
6890 #if 0
6891 /*-----------------------------------------------------------------*/
6892 /* shiftL2Left2Result - shift left two bytes from left to result   */
6893 /*-----------------------------------------------------------------*/
6894 static void shiftL2Left2Result (operand *left, int offl,
6895                                                                 operand *result, int offr, int shCount)
6896 {
6897         FENTRY;
6898         
6899         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6900         
6901         if(pic14_sameRegs(AOP(result), AOP(left))) {
6902                 switch(shCount) {
6903                 case 0:
6904                         break;
6905                 case 1:
6906                 case 2:
6907                 case 3:
6908                         
6909                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
6910                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6911                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
6912                         
6913                         while(--shCount) {
6914                                 emitCLRC;
6915                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6916                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6917                         }
6918                         
6919                         break;
6920                 case 4:
6921                 case 5:
6922                         emitpcode(POC_MOVLW, popGetLit(0x0f));
6923                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
6924                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
6925                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6926                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
6927                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
6928                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6929                         if(shCount >=5) {
6930                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6931                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6932                         }
6933                         break;
6934                 case 6:
6935                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6936                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6937                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
6938                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6939                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6940                         emitpcode(POC_ANDLW,popGetLit(0xc0));
6941                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6942                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
6943                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
6944                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6945                         break;
6946                 case 7:
6947                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
6948                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
6949                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6950                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
6951                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
6952                 }
6953                 
6954         } else {
6955                 switch(shCount) {
6956                 case 0:
6957                         break;
6958                 case 1:
6959                 case 2:
6960                 case 3:
6961                 /* note, use a mov/add for the shift since the mov has a
6962                         chance of getting optimized out */
6963                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6964                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6965                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
6966                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
6967                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6968                         
6969                         while(--shCount) {
6970                                 emitCLRC;
6971                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6972                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6973                         }
6974                         break;
6975                         
6976                 case 4:
6977                 case 5:
6978                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
6979                         emitpcode(POC_ANDLW, popGetLit(0xF0));
6980                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
6981                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6982                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6983                         emitpcode(POC_ANDLW, popGetLit(0xF0));
6984                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
6985                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
6986                         
6987                         
6988                         if(shCount == 5) {
6989                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
6990                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
6991                         }
6992                         break;
6993                 case 6:
6994                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
6995                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
6996                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
6997                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6998                         
6999                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7000                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7001                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7002                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7003                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7004                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7005                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7006                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7007                         break;
7008                 case 7:
7009                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7010                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7011                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7012                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7013                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7014                 }
7015         }
7016         
7017 }
7018
7019 /*-----------------------------------------------------------------*/
7020 /* shiftR2Left2Result - shift right two bytes from left to result  */
7021 /*-----------------------------------------------------------------*/
7022 static void shiftR2Left2Result (operand *left, int offl,
7023                                                                 operand *result, int offr,
7024                                                                 int shCount, int sign)
7025 {
7026         int same=0;
7027         
7028         FENTRY;
7029         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7030         same = pic14_sameRegs(AOP(result), AOP(left));
7031         
7032         if(same && ((offl + MSB16) == offr)){
7033                 same=1;
7034                 /* don't crash result[offr] */
7035                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7036                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7037         }
7038         /* else {
7039         movLeft2Result(left,offl, result, offr);
7040         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7041         }
7042         */
7043         /* a:x >> shCount (x = lsb(result))*/
7044         /*
7045         if(sign)
7046         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7047         else {
7048         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7049         */
7050         switch(shCount) {
7051         case 0:
7052                 break;
7053         case 1:
7054         case 2:
7055         case 3:
7056                 if(sign)
7057                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7058                 else
7059                         emitCLRC;
7060                 
7061                 if(same) {
7062                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7063                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7064                 } else {
7065                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7066                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7067                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7068                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7069                 }
7070                 
7071                 while(--shCount) {
7072                         if(sign)
7073                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7074                         else
7075                                 emitCLRC;
7076                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7077                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7078                 }
7079                 break;
7080         case 4:
7081         case 5:
7082                 if(same) {
7083                         
7084                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7085                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7086                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7087                         
7088                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7089                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7090                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7091                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7092                 } else {
7093                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7094                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7095                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7096                         
7097                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7098                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7099                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7100                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7101                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7102                 }
7103                 
7104                 if(shCount >=5) {
7105                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7106                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7107                 }
7108                 
7109                 if(sign) {
7110                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7111                         emitpcode(POC_BTFSC, 
7112                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7113                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7114                 }
7115                 
7116                 break;
7117                 
7118         case 6:
7119                 if(same) {
7120                         
7121                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7122                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7123                         
7124                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7125                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7126                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7127                         emitpcode(POC_ANDLW,popGetLit(0x03));
7128                         if(sign) {
7129                                 emitpcode(POC_BTFSC, 
7130                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7131                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7132                         }
7133                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7134                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7135                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7136                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7137                 } else {
7138                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7139                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7140                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7141                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7142                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7143                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7144                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7145                         emitpcode(POC_ANDLW,popGetLit(0x03));
7146                         if(sign) {
7147                                 emitpcode(POC_BTFSC, 
7148                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7149                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7150                         }
7151                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7152                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7153                         
7154                         
7155                 }
7156                 
7157                 break;
7158         case 7:
7159                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7160                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7161                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7162                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7163                 if(sign) {
7164                         emitSKPNC;
7165                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7166                 } else 
7167                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7168   }
7169 }
7170
7171 /*-----------------------------------------------------------------*/
7172 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7173 /*-----------------------------------------------------------------*/
7174 static void shiftLLeftOrResult (operand *left, int offl,
7175                                                                 operand *result, int offr, int shCount)
7176 {
7177         FENTRY;
7178         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7179         
7180         /* shift left accumulator */
7181         AccLsh(left,offl,shCount);
7182         /* or with result */
7183         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7184         assert ( !"broken (modifies left, fails for left==result))" );
7185 }
7186
7187 /*-----------------------------------------------------------------*/
7188 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7189 /*-----------------------------------------------------------------*/
7190 static void shiftRLeftOrResult (operand *left, int offl,
7191                                                                 operand *result, int offr, int shCount)
7192 {
7193         FENTRY;
7194         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7195         
7196         /* shift right accumulator */
7197         AccRsh(left,offl,shCount);
7198         /* or with result */
7199         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7200         assert ( !"broken (modifies left, fails for left==result))" );
7201 }
7202
7203 /*-----------------------------------------------------------------*/
7204 /* genlshOne - left shift a one byte quantity by known count       */
7205 /*-----------------------------------------------------------------*/
7206 static void genlshOne (operand *result, operand *left, int shCount)
7207 {       
7208         FENTRY;
7209         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7210         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7211 }
7212
7213 /*-----------------------------------------------------------------*/
7214 /* genlshTwo - left shift two bytes by known amount != 0           */
7215 /*-----------------------------------------------------------------*/
7216 static void genlshTwo (operand *result,operand *left, int shCount)
7217 {
7218         int size;
7219         
7220         FENTRY;
7221         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7222         size = pic14_getDataSize(result);
7223         
7224         /* if shCount >= 8 */
7225         if (shCount >= 8) {
7226                 shCount -= 8 ;
7227                 
7228                 if (size > 1){
7229                         if (shCount)
7230                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7231                         else 
7232                                 movLeft2Result(left, LSB, result, MSB16);
7233                 }
7234                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7235         }
7236         
7237         /*  1 <= shCount <= 7 */
7238         else {  
7239                 if(size == 1)
7240                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7241                 else 
7242                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7243         }
7244 }
7245
7246 /*-----------------------------------------------------------------*/
7247 /* shiftLLong - shift left one long from left to result            */
7248 /* offl = LSB or MSB16                                             */
7249 /*-----------------------------------------------------------------*/
7250 static void shiftLLong (operand *left, operand *result, int offr )
7251 {
7252         char *l;
7253         int size = AOP_SIZE(result);
7254         
7255         FENTRY;
7256         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7257         if(size >= LSB+offr){
7258                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7259                 MOVA(l);
7260                 pic14_emitcode("add","a,acc");
7261                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7262                         size >= MSB16+offr && offr != LSB )
7263                         pic14_emitcode("xch","a,%s",
7264                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7265                 else      
7266                         aopPut(AOP(result),"a",LSB+offr);
7267         }
7268         
7269         if(size >= MSB16+offr){
7270                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7271                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7272                         MOVA(l);
7273                 }
7274                 pic14_emitcode("rlc","a");
7275                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7276                         size >= MSB24+offr && offr != LSB)
7277                         pic14_emitcode("xch","a,%s",
7278                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7279                 else      
7280                         aopPut(AOP(result),"a",MSB16+offr);
7281         }
7282         
7283         if(size >= MSB24+offr){
7284                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7285                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7286                         MOVA(l);
7287                 }
7288                 pic14_emitcode("rlc","a");
7289                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7290                         size >= MSB32+offr && offr != LSB )
7291                         pic14_emitcode("xch","a,%s",
7292                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7293                 else      
7294                         aopPut(AOP(result),"a",MSB24+offr);
7295         }
7296         
7297         if(size > MSB32+offr){
7298                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7299                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7300                         MOVA(l);  
7301                 }
7302                 pic14_emitcode("rlc","a");
7303                 aopPut(AOP(result),"a",MSB32+offr);
7304         }
7305         if(offr != LSB)
7306                 aopPut(AOP(result),zero,LSB);       
7307 }
7308
7309 /*-----------------------------------------------------------------*/
7310 /* genlshFour - shift four byte by a known amount != 0             */
7311 /*-----------------------------------------------------------------*/
7312 static void genlshFour (operand *result, operand *left, int shCount)
7313 {
7314         int size;
7315         
7316         FENTRY;
7317         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7318         size = AOP_SIZE(result);
7319         
7320         /* if shifting more that 3 bytes */
7321         if (shCount >= 24 ) {
7322                 shCount -= 24;
7323                 if (shCount)
7324                 /* lowest order of left goes to the highest
7325                 order of the destination */
7326                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7327                 else
7328                         movLeft2Result(left, LSB, result, MSB32);
7329                 aopPut(AOP(result),zero,LSB);
7330                 aopPut(AOP(result),zero,MSB16);
7331                 aopPut(AOP(result),zero,MSB32);
7332                 return;
7333         }
7334         
7335         /* more than two bytes */
7336         else if ( shCount >= 16 ) {
7337                 /* lower order two bytes goes to higher order two bytes */
7338                 shCount -= 16;
7339                 /* if some more remaining */
7340                 if (shCount)
7341                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7342                 else {
7343                         movLeft2Result(left, MSB16, result, MSB32);
7344                         movLeft2Result(left, LSB, result, MSB24);
7345                 }
7346                 aopPut(AOP(result),zero,MSB16);
7347                 aopPut(AOP(result),zero,LSB);
7348                 return;
7349         }    
7350         
7351         /* if more than 1 byte */
7352         else if ( shCount >= 8 ) {
7353                 /* lower order three bytes goes to higher order  three bytes */
7354                 shCount -= 8;
7355                 if(size == 2){
7356                         if(shCount)
7357                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7358                         else
7359                                 movLeft2Result(left, LSB, result, MSB16);
7360                 }
7361                 else{   /* size = 4 */
7362                         if(shCount == 0){
7363                                 movLeft2Result(left, MSB24, result, MSB32);
7364                                 movLeft2Result(left, MSB16, result, MSB24);
7365                                 movLeft2Result(left, LSB, result, MSB16);
7366                                 aopPut(AOP(result),zero,LSB);
7367                         }
7368                         else if(shCount == 1)
7369                                 shiftLLong(left, result, MSB16);
7370                         else{
7371                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7372                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7373                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7374                                 aopPut(AOP(result),zero,LSB);
7375                         }
7376                 }
7377         }
7378         
7379         /* 1 <= shCount <= 7 */
7380         else if(shCount <= 2){
7381                 shiftLLong(left, result, LSB);
7382                 if(shCount == 2)
7383                         shiftLLong(result, result, LSB);
7384         }
7385         /* 3 <= shCount <= 7, optimize */
7386         else{
7387                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7388                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7389                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7390         }
7391 }
7392 #endif
7393
7394 #if 0
7395 /*-----------------------------------------------------------------*/
7396 /* genLeftShiftLiteral - left shifting by known count              */
7397 /*-----------------------------------------------------------------*/
7398 static void genLeftShiftLiteral (operand *left,
7399                                                                  operand *right,
7400                                                                  operand *result,
7401                                                                  iCode *ic)
7402 {    
7403         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7404         //int size;
7405         
7406         FENTRY;
7407         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7408         freeAsmop(right,NULL,ic,TRUE);
7409         
7410         aopOp(left,ic,FALSE);
7411         aopOp(result,ic,FALSE);
7412
7413         size = getSize(operandType(result));
7414         
7415 #if VIEW_SIZE
7416         pic14_emitcode("; shift left ","result %d, left %d",size,
7417                 AOP_SIZE(left));
7418 #endif
7419         
7420         /* I suppose that the left size >= result size */
7421         if(shCount == 0){
7422                 while(size--){
7423                         movLeft2Result(left, size, result, size);
7424                 }
7425         }
7426         
7427         else if(shCount >= (size * 8))
7428                 while(size--)
7429                         aopPut(AOP(result),zero,size);
7430                 else{
7431                         switch (size) {
7432                         case 1:
7433                                 genlshOne (result,left,shCount);
7434                                 break;
7435                                 
7436                         case 2:
7437                         case 3:
7438                                 genlshTwo (result,left,shCount);
7439                                 break;
7440                                 
7441                         case 4:
7442                                 genlshFour (result,left,shCount);
7443                                 break;
7444                         }
7445                 }
7446                 freeAsmop(left,NULL,ic,TRUE);
7447                 freeAsmop(result,NULL,ic,TRUE);
7448 }
7449 #endif
7450
7451 /*-----------------------------------------------------------------*
7452 * genMultiAsm - repeat assembly instruction for size of register.
7453 * if endian == 1, then the high byte (i.e base address + size of 
7454 * register) is used first else the low byte is used first;
7455 *-----------------------------------------------------------------*/
7456 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7457 {
7458         
7459         int offset = 0;
7460         
7461         FENTRY;
7462         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7463         
7464         if(!reg)
7465                 return;
7466         
7467         if(!endian) {
7468                 endian = 1;
7469         } else {
7470                 endian = -1;
7471                 offset = size-1;
7472         }
7473         
7474         while(size--) {
7475                 emitpcode(poc,    popGet(AOP(reg),offset));
7476                 offset += endian;
7477         }
7478         
7479 }
7480 /*-----------------------------------------------------------------*/
7481 /* genLeftShift - generates code for left shifting                 */
7482 /*-----------------------------------------------------------------*/
7483 static void genLeftShift (iCode *ic)
7484 {
7485         operand *left,*right, *result;
7486         int size, offset;
7487         unsigned long lit = 0L;
7488         char *l;
7489         symbol *tlbl , *tlbl1;
7490         pCodeOp *pctemp;
7491         
7492         FENTRY;
7493         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7494         
7495         right = IC_RIGHT(ic);
7496         left  = IC_LEFT(ic);
7497         result = IC_RESULT(ic);
7498         
7499         aopOp(right,ic,FALSE);
7500         aopOp(left,ic,FALSE);
7501         aopOp(result,ic,FALSE);
7502         
7503         
7504         /* if the shift count is known then do it 
7505         as efficiently as possible */
7506         if (AOP_TYPE(right) == AOP_LIT) {
7507                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7508                 return ;
7509         }
7510         
7511         /* shift count is unknown then we have to form 
7512         a loop get the loop count in B : Note: we take
7513         only the lower order byte since shifting
7514         more that 32 bits make no sense anyway, ( the
7515         largest size of an object can be only 32 bits ) */  
7516         
7517         
7518         /* now move the left to the result if they are not the
7519         same */
7520         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7521                 AOP_SIZE(result) > 1) {
7522                 
7523                 size = AOP_SIZE(result);
7524                 offset=0;
7525                 while (size--) {
7526                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7527                         if (*l == '@' && (IS_AOP_PREG(result))) {
7528                                 
7529                                 pic14_emitcode("mov","a,%s",l);
7530                                 aopPut(AOP(result),"a",offset);
7531                         } else {
7532                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7533                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7534                                 //aopPut(AOP(result),l,offset);
7535                         }
7536                         offset++;
7537                 }
7538         }
7539         
7540         if(AOP_TYPE(left) == AOP_LIT)
7541                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7542
7543         size = AOP_SIZE(result);
7544         
7545         /* if it is only one byte then */
7546         if (size == 1) {
7547                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7548                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7549                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7550                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7551                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7552                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7553                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7554                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7555                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7556                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7557                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7558                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7559                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7560                 } else {
7561                         
7562                         tlbl = newiTempLabel(NULL);
7563                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7564                                 if (AOP_TYPE(left) == AOP_LIT)
7565                                         emitpcode(POC_MOVLW,  popGetLit(lit));
7566                                 else
7567                                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7568                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7569                         }
7570                         
7571                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7572                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7573                         emitpLabel(tlbl->key);
7574                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7575                         emitpcode(POC_ADDLW,  popGetLit(1));
7576                         emitSKPC;
7577                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7578                 }
7579                 goto release ;
7580         }
7581         
7582         if (pic14_sameRegs(AOP(left),AOP(result))) {
7583                 
7584                 tlbl = newiTempLabel(NULL);
7585                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7586                 genMultiAsm(POC_RRF, result, size,1);
7587                 emitpLabel(tlbl->key);
7588                 genMultiAsm(POC_RLF, result, size,0);
7589                 emitpcode(POC_ADDLW,  popGetLit(1));
7590                 emitSKPC;
7591                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7592                 goto release;
7593         }
7594         
7595         //tlbl = newiTempLabel(NULL);
7596         //offset = 0 ;   
7597         //tlbl1 = newiTempLabel(NULL);
7598         
7599         //reAdjustPreg(AOP(result));    
7600         
7601         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7602         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7603         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7604         //MOVA(l);
7605         //pic14_emitcode("add","a,acc");         
7606         //aopPut(AOP(result),"a",offset++);
7607         //while (--size) {
7608         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7609         //  MOVA(l);
7610         //  pic14_emitcode("rlc","a");         
7611         //  aopPut(AOP(result),"a",offset++);
7612         //}
7613         //reAdjustPreg(AOP(result));
7614         
7615         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7616         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7617         
7618         
7619         tlbl = newiTempLabel(NULL);
7620         tlbl1= newiTempLabel(NULL);
7621         
7622         size = AOP_SIZE(result);
7623         offset = 1;
7624         
7625         pctemp = popGetTempReg();  /* grab a temporary working register. */
7626         
7627         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7628         
7629         /* offset should be 0, 1 or 3 */
7630         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7631         emitSKPNZ;
7632         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7633         
7634         emitpcode(POC_MOVWF, pctemp);
7635         
7636         
7637         emitpLabel(tlbl->key);
7638         
7639         emitCLRC;
7640         emitpcode(POC_RLF,  popGet(AOP(result),0));
7641         while(--size)
7642                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7643         
7644         emitpcode(POC_DECFSZ,  pctemp);
7645         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7646         emitpLabel(tlbl1->key);
7647         
7648         popReleaseTempReg(pctemp);
7649         
7650         
7651 release:
7652         freeAsmop (right,NULL,ic,TRUE);
7653         freeAsmop(left,NULL,ic,TRUE);
7654         freeAsmop(result,NULL,ic,TRUE);
7655 }
7656
7657 #if 0
7658 /*-----------------------------------------------------------------*/
7659 /* genrshOne - right shift a one byte quantity by known count      */
7660 /*-----------------------------------------------------------------*/
7661 static void genrshOne (operand *result, operand *left,
7662                                            int shCount, int sign)
7663 {
7664         FENTRY;
7665         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7666         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7667 }
7668
7669 /*-----------------------------------------------------------------*/
7670 /* genrshTwo - right shift two bytes by known amount != 0          */
7671 /*-----------------------------------------------------------------*/
7672 static void genrshTwo (operand *result,operand *left,
7673                                            int shCount, int sign)
7674 {
7675         FENTRY;
7676         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7677         /* if shCount >= 8 */
7678         if (shCount >= 8) {
7679                 shCount -= 8 ;
7680                 if (shCount)
7681                         shiftR1Left2Result(left, MSB16, result, LSB,
7682                         shCount, sign);
7683                 else
7684                         movLeft2Result(left, MSB16, result, LSB);
7685                 
7686                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7687                 
7688                 if(sign) {
7689                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7690                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7691                 }
7692         }
7693         
7694         /*  1 <= shCount <= 7 */
7695         else
7696                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7697 }
7698
7699 /*-----------------------------------------------------------------*/
7700 /* shiftRLong - shift right one long from left to result           */
7701 /* offl = LSB or MSB16                                             */
7702 /*-----------------------------------------------------------------*/
7703 static void shiftRLong (operand *left, int offl,
7704                                                 operand *result, int sign)
7705 {
7706         int size, same;
7707         
7708         FENTRY;
7709         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7710         
7711         size = AOP_SIZE(left);
7712         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7713         
7714         if (sign)
7715                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7716         else
7717                 emitCLRC;
7718
7719         assert (offl >= 0 && offl < size);
7720
7721         same = pic14_sameRegs (AOP(left), AOP(result));
7722
7723         /* perform the shift */
7724         while (size--)
7725         {
7726                 if (same && !offl) {
7727                         emitpcode (POC_RRF, popGet (AOP(result), size));
7728                 } else {
7729                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7730                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7731                 }
7732         } // while
7733
7734         addSign (result, AOP_SIZE(left) - offl, sign);
7735 }
7736
7737 /*-----------------------------------------------------------------*/
7738 /* genrshFour - shift four byte by a known amount != 0             */
7739 /*-----------------------------------------------------------------*/
7740 static void genrshFour (operand *result, operand *left,
7741                                                 int shCount, int sign)
7742 {
7743         FENTRY;
7744         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7745         /* if shifting more that 3 bytes */
7746         if(shCount >= 24 ) {
7747                 shCount -= 24;
7748                 if(shCount)
7749                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7750                 else
7751                         movLeft2Result(left, MSB32, result, LSB);
7752                 
7753                 addSign(result, MSB16, sign);
7754         }
7755         else if(shCount >= 16){
7756                 shCount -= 16;
7757                 if(shCount)
7758                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7759                 else{
7760                         movLeft2Result(left, MSB24, result, LSB);
7761                         movLeft2Result(left, MSB32, result, MSB16);
7762                 }
7763                 addSign(result, MSB24, sign);
7764         }
7765         else if(shCount >= 8){
7766                 shCount -= 8;
7767                 if(shCount == 1)
7768                         shiftRLong(left, MSB16, result, sign);
7769                 else if(shCount == 0){
7770                         movLeft2Result(left, MSB16, result, LSB);
7771                         movLeft2Result(left, MSB24, result, MSB16);
7772                         movLeft2Result(left, MSB32, result, MSB24);
7773                         addSign(result, MSB32, sign);
7774                 }
7775                 else{
7776                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7777                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7778                         /* the last shift is signed */
7779                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7780                         addSign(result, MSB32, sign);
7781                 }
7782         }
7783         else{   /* 1 <= shCount <= 7 */
7784                 if(shCount <= 2){
7785                         shiftRLong(left, LSB, result, sign);
7786                         if(shCount == 2)
7787                                 shiftRLong(result, LSB, result, sign);
7788                 }
7789                 else{
7790                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7791                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7792                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7793                 }
7794         }
7795 }
7796
7797 /*-----------------------------------------------------------------*/
7798 /* genRightShiftLiteral - right shifting by known count            */
7799 /*-----------------------------------------------------------------*/
7800 static void genRightShiftLiteral (operand *left,
7801                                                                   operand *right,
7802                                                                   operand *result,
7803                                                                   iCode *ic,
7804                                                                   int sign)
7805 {    
7806         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7807         int lsize,res_size;
7808         
7809         FENTRY;
7810         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7811         freeAsmop(right,NULL,ic,TRUE);
7812         
7813         aopOp(left,ic,FALSE);
7814         aopOp(result,ic,FALSE);
7815         
7816 #if VIEW_SIZE
7817         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7818                 AOP_SIZE(left));
7819 #endif
7820         
7821         lsize = pic14_getDataSize(left);
7822         res_size = pic14_getDataSize(result);
7823         /* test the LEFT size !!! */
7824         
7825         /* I suppose that the left size >= result size */
7826         if(shCount == 0){
7827                 while(res_size--)
7828                         movLeft2Result(left, res_size, result, res_size);
7829         }
7830         
7831         else if(shCount >= (lsize * 8)){
7832                 
7833                 if(res_size == 1) {
7834                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
7835                         if(sign) {
7836                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7837                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
7838                         }
7839                 } else {
7840                         
7841                         if(sign) {
7842                                 emitpcode(POC_MOVLW, popGetLit(0));
7843                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7844                                 emitpcode(POC_MOVLW, popGetLit(0xff));
7845                                 while(res_size--)
7846                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
7847                                 
7848                         } else {
7849                                 
7850                                 while(res_size--)
7851                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
7852                         }
7853                 }
7854         } else {
7855                 
7856                 switch (res_size) {
7857                 case 1:
7858                         genrshOne (result,left,shCount,sign);
7859                         break;
7860                         
7861                 case 2:
7862                         genrshTwo (result,left,shCount,sign);
7863                         break;
7864                         
7865                 case 4:
7866                         genrshFour (result,left,shCount,sign);
7867                         break;
7868                 default :
7869                         break;
7870                 }
7871                 
7872         }
7873
7874         freeAsmop(left,NULL,ic,TRUE);
7875         freeAsmop(result,NULL,ic,TRUE);
7876 }
7877 #endif
7878
7879 /*-----------------------------------------------------------------*/
7880 /* genSignedRightShift - right shift of signed number              */
7881 /*-----------------------------------------------------------------*/
7882 static void genSignedRightShift (iCode *ic)
7883 {
7884         operand *right, *left, *result;
7885         int size, offset;
7886         //  char *l;
7887         symbol *tlbl, *tlbl1 ;
7888         pCodeOp *pctemp;
7889         
7890         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7891         
7892         /* we do it the hard way put the shift count in b
7893         and loop thru preserving the sign */
7894         FENTRY;
7895         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7896         
7897         right = IC_RIGHT(ic);
7898         left  = IC_LEFT(ic);
7899         result = IC_RESULT(ic);
7900         
7901         aopOp(right,ic,FALSE);  
7902         aopOp(left,ic,FALSE);
7903         aopOp(result,ic,FALSE);
7904         
7905         
7906         if ( AOP_TYPE(right) == AOP_LIT) {
7907                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
7908                 //genRightShiftLiteral (left,right,result,ic,1);
7909                 return ;
7910         }
7911         /* shift count is unknown then we have to form 
7912         a loop get the loop count in B : Note: we take
7913         only the lower order byte since shifting
7914         more that 32 bits make no sense anyway, ( the
7915         largest size of an object can be only 32 bits ) */  
7916         
7917         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
7918         //pic14_emitcode("inc","b");
7919         //freeAsmop (right,NULL,ic,TRUE);
7920         //aopOp(left,ic,FALSE);
7921         //aopOp(result,ic,FALSE);
7922         
7923         /* now move the left to the result if they are not the
7924         same */
7925         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7926                 AOP_SIZE(result) > 1) {
7927                 
7928                 size = AOP_SIZE(result);
7929                 offset=0;
7930                 while (size--) { 
7931                         /*
7932                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7933                         if (*l == '@' && IS_AOP_PREG(result)) {
7934                                 pic14_emitcode("mov","a,%s",l);
7935                                 aopPut(AOP(result),"a",offset);
7936                         } else
7937                         aopPut(AOP(result),l,offset);
7938                         */
7939                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7940                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7941                         
7942                         offset++;
7943                 }
7944         }
7945         
7946         /* mov the highest order bit to OVR */    
7947         tlbl = newiTempLabel(NULL);
7948         tlbl1= newiTempLabel(NULL);
7949         
7950         size = AOP_SIZE(result);
7951         offset = size - 1;
7952         
7953         pctemp = popGetTempReg();  /* grab a temporary working register. */
7954         
7955         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7956         
7957         /* offset should be 0, 1 or 3 */
7958         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7959         emitSKPNZ;
7960         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7961         
7962         emitpcode(POC_MOVWF, pctemp);
7963         
7964         
7965         emitpLabel(tlbl->key);
7966         
7967         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
7968         emitpcode(POC_RRF,   popGet(AOP(result),offset));
7969         
7970         while(--size) {
7971                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
7972         }
7973         
7974         emitpcode(POC_DECFSZ,  pctemp);
7975         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7976         emitpLabel(tlbl1->key);
7977         
7978         popReleaseTempReg(pctemp);
7979 #if 0
7980         size = AOP_SIZE(result);
7981         offset = size - 1;
7982         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
7983         pic14_emitcode("rlc","a");
7984         pic14_emitcode("mov","ov,c");
7985         /* if it is only one byte then */
7986         if (size == 1) {
7987                 l = aopGet(AOP(left),0,FALSE,FALSE);
7988                 MOVA(l);
7989                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
7990                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
7991                 pic14_emitcode("mov","c,ov");
7992                 pic14_emitcode("rrc","a");
7993                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7994                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7995                 aopPut(AOP(result),"a",0);
7996                 goto release ;
7997         }
7998         
7999         reAdjustPreg(AOP(result));
8000         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8001         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8002         pic14_emitcode("mov","c,ov");
8003         while (size--) {
8004                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8005                 MOVA(l);
8006                 pic14_emitcode("rrc","a");         
8007                 aopPut(AOP(result),"a",offset--);
8008         }
8009         reAdjustPreg(AOP(result));
8010         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8011         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8012         
8013 release:
8014 #endif
8015         
8016         freeAsmop(left,NULL,ic,TRUE);
8017         freeAsmop(result,NULL,ic,TRUE);
8018         freeAsmop(right,NULL,ic,TRUE);
8019 }
8020
8021 /*-----------------------------------------------------------------*/
8022 /* genRightShift - generate code for right shifting                */
8023 /*-----------------------------------------------------------------*/
8024 static void genRightShift (iCode *ic)
8025 {
8026         operand *right, *left, *result;
8027         sym_link *retype ;
8028         int size, offset;
8029         char *l;
8030         symbol *tlbl, *tlbl1 ;
8031         
8032         FENTRY;
8033         /* if signed then we do it the hard way preserve the
8034         sign bit moving it inwards */
8035         retype = getSpec(operandType(IC_RESULT(ic)));
8036         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8037         
8038         if (!SPEC_USIGN(retype)) {
8039                 genSignedRightShift (ic);
8040                 return ;
8041         }
8042         
8043         /* signed & unsigned types are treated the same : i.e. the
8044         signed is NOT propagated inwards : quoting from the
8045         ANSI - standard : "for E1 >> E2, is equivalent to division
8046         by 2**E2 if unsigned or if it has a non-negative value,
8047         otherwise the result is implementation defined ", MY definition
8048         is that the sign does not get propagated */
8049         
8050         right = IC_RIGHT(ic);
8051         left  = IC_LEFT(ic);
8052         result = IC_RESULT(ic);
8053         
8054         aopOp(right,ic,FALSE);
8055         aopOp(left,ic,FALSE);
8056         aopOp(result,ic,FALSE);
8057         
8058         /* if the shift count is known then do it 
8059         as efficiently as possible */
8060         if (AOP_TYPE(right) == AOP_LIT) {
8061                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
8062                 //genRightShiftLiteral (left,right,result,ic, 0);
8063                 return ;
8064         }
8065         
8066         /* shift count is unknown then we have to form 
8067         a loop get the loop count in B : Note: we take
8068         only the lower order byte since shifting
8069         more that 32 bits make no sense anyway, ( the
8070         largest size of an object can be only 32 bits ) */  
8071         
8072         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8073         pic14_emitcode("inc","b");
8074         
8075         /* now move the left to the result if they are not the
8076         same */
8077         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8078                 AOP_SIZE(result) > 1) {
8079                 
8080                 size = AOP_SIZE(result);
8081                 offset=0;
8082                 while (size--) {
8083                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8084                         if (*l == '@' && IS_AOP_PREG(result)) {
8085                                 
8086                                 pic14_emitcode("mov","a,%s",l);
8087                                 aopPut(AOP(result),"a",offset);
8088                         } else
8089                                 aopPut(AOP(result),l,offset);
8090                         offset++;
8091                 }
8092         }
8093         
8094         tlbl = newiTempLabel(NULL);
8095         tlbl1= newiTempLabel(NULL);
8096         size = AOP_SIZE(result);
8097         offset = size - 1;
8098         
8099         /* if it is only one byte then */
8100         if (size == 1) {
8101                 
8102                 tlbl = newiTempLabel(NULL);
8103                 if (!pic14_sameRegs(AOP(left),AOP(result))) {
8104                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
8105                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
8106                 }
8107                 
8108                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
8109                 emitpcode(POC_RLF,    popGet(AOP(result),0));
8110                 emitpLabel(tlbl->key);
8111                 emitpcode(POC_RRF,    popGet(AOP(result),0));
8112                 emitpcode(POC_ADDLW,  popGetLit(1));
8113                 emitSKPC;
8114                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8115                 
8116                 goto release ;
8117         }
8118         
8119         reAdjustPreg(AOP(result));
8120         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8121         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8122         CLRC;
8123         while (size--) {
8124                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8125                 MOVA(l);
8126                 pic14_emitcode("rrc","a");         
8127                 aopPut(AOP(result),"a",offset--);
8128         }
8129         reAdjustPreg(AOP(result));
8130         
8131         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8132         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8133         
8134 release:
8135         freeAsmop(left,NULL,ic,TRUE);
8136         freeAsmop (right,NULL,ic,TRUE);
8137         freeAsmop(result,NULL,ic,TRUE);
8138 }
8139
8140 /*-----------------------------------------------------------------*/
8141 /* genUnpackBits - generates code for unpacking bits               */
8142 /*-----------------------------------------------------------------*/
8143 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
8144 {    
8145         int shCnt;
8146         int offset = 0;       /* result byte offset */
8147         int rsize;            /* result size */
8148         int rlen = 0;         /* remaining bitfield length */
8149         sym_link *etype;      /* bitfield type information */
8150         int blen;             /* bitfield length */
8151         int bstr;             /* bitfield starting bit within byte */
8152
8153         FENTRY;
8154         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8155         etype = getSpec(operandType(result));
8156         rsize = getSize (operandType (result));
8157         blen = SPEC_BLEN (etype);
8158         bstr = SPEC_BSTR (etype);
8159         
8160         /* single bit field case */
8161         if (blen == 1) {
8162                 if (ifx) { /* that is for an if statement */
8163                         pCodeOp *pcop;
8164                         resolvedIfx rIfx;
8165                         resolveIfx(&rIfx,ifx);
8166                         if (ptype == -1) /* direct */
8167                                 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8168                         else
8169                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8170                         emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8171                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8172                         ifx->generated=1;
8173                 } else {
8174                         pCodeOp *pcop;
8175                         if (ptype == -1) /* direct */
8176                                 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8177                         else
8178                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8179                         emitpcode(POC_BTFSC,pcop);
8180                         emitpcode(POC_BSF,newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0));
8181
8182                         if (ptype == -1) /* direct */
8183                                 pcop = newpCodeOpBit(AOP(left)->aopu.pcop->name,bstr,0);
8184                         else
8185                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8186                         emitpcode(POC_BTFSS,pcop);
8187                         emitpcode(POC_BCF,newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0));
8188                 }
8189                 return;
8190         }
8191
8192         /* read the first byte  */
8193         switch (ptype) {
8194                 
8195         case POINTER:
8196         case IPOINTER:
8197 //              pic14_emitcode("mov","a,@%s",rname);
8198                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8199                 break;
8200                 
8201         case PPOINTER:
8202                 pic14_emitcode("movx","a,@%s",rname);
8203                 break;
8204                 
8205         case FPOINTER:
8206                 pic14_emitcode("movx","a,@dptr");
8207                 break;
8208                 
8209         case CPOINTER:
8210                 pic14_emitcode("clr","a");
8211                 pic14_emitcode("movc","a","@a+dptr");
8212                 break;
8213                 
8214         case GPOINTER:
8215                 pic14_emitcode("lcall","__gptrget");
8216                 break;
8217         }
8218
8219         /* if we have bitdisplacement then it fits   */
8220         /* into this byte completely or if length is */
8221         /* less than a byte                          */
8222         if ((shCnt = SPEC_BSTR(etype)) || blen <= 8)  {
8223                 
8224                 /* shift right acc */
8225                 AccRsh(left,0,shCnt);
8226                 
8227                 pic14_emitcode("anl","a,#0x%02x",
8228                         ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8229                 aopPut(AOP(result),"a",offset);
8230                 return ;
8231         }
8232         
8233         /* bit field did not fit in a byte  */
8234         rlen = SPEC_BLEN(etype) - 8;
8235         aopPut(AOP(result),"a",offset++);
8236         
8237         while (1)  {
8238                 
8239                 switch (ptype) {
8240                 case POINTER:
8241                 case IPOINTER:
8242                         pic14_emitcode("inc","%s",rname);
8243                         pic14_emitcode("mov","a,@%s",rname);
8244                         break;
8245                         
8246                 case PPOINTER:
8247                         pic14_emitcode("inc","%s",rname);
8248                         pic14_emitcode("movx","a,@%s",rname);
8249                         break;
8250                         
8251                 case FPOINTER:
8252                         pic14_emitcode("inc","dptr");
8253                         pic14_emitcode("movx","a,@dptr");
8254                         break;
8255                         
8256                 case CPOINTER:
8257                         pic14_emitcode("clr","a");
8258                         pic14_emitcode("inc","dptr");
8259                         pic14_emitcode("movc","a","@a+dptr");
8260                         break;
8261                         
8262                 case GPOINTER:
8263                         pic14_emitcode("inc","dptr");
8264                         pic14_emitcode("lcall","__gptrget");
8265                         break;
8266                 }
8267                 
8268                 rlen -= 8;            
8269                 /* if we are done */
8270                 if ( rlen <= 0 )
8271                         break ;
8272                 
8273                 aopPut(AOP(result),"a",offset++);
8274                 
8275         }
8276         
8277         if (rlen) {
8278                 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8279                 aopPut(AOP(result),"a",offset);        
8280         }
8281         
8282         return ;
8283 }
8284
8285 #if 1
8286 /*-----------------------------------------------------------------*/
8287 /* genDataPointerGet - generates code when ptr offset is known     */
8288 /*-----------------------------------------------------------------*/
8289 static void genDataPointerGet (operand *left, 
8290         operand *result, 
8291         iCode *ic)
8292 {
8293         int size , offset = 0;
8294                 
8295         FENTRY;
8296         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8297         
8298         
8299         /* optimization - most of the time, left and result are the same
8300         * address, but different types. for the pic code, we could omit
8301         * the following
8302         */
8303         aopOp(result,ic,TRUE);
8304         
8305         if (pic14_sameRegs (AOP(left), AOP(result)))
8306                 return;
8307         
8308         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8309         
8310         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8311         
8312         size = AOP_SIZE(result);
8313         if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
8314         
8315         while (size--) {
8316                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8317                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8318                 offset++;
8319         }
8320         
8321         freeAsmop(left,NULL,ic,TRUE);
8322         freeAsmop(result,NULL,ic,TRUE);
8323 }
8324 #endif
8325 /*-----------------------------------------------------------------*/
8326 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8327 /*-----------------------------------------------------------------*/
8328 static void genNearPointerGet (operand *left, 
8329                                                            operand *result, 
8330                                                            iCode *ic)
8331 {
8332         asmop *aop = NULL;
8333         sym_link *ltype = operandType(left);
8334         sym_link *rtype = operandType(result);
8335         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8336         int direct = 0;
8337
8338         FENTRY;
8339         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8340         
8341         
8342         aopOp(left,ic,FALSE);
8343         
8344         /* if left is rematerialisable and
8345         result is not bit variable type and
8346         the left is pointer to data space i.e
8347         lower 128 bytes of space */
8348         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8349                 !IS_BITVAR(retype)         &&
8350                 DCL_TYPE(ltype) == POINTER) {
8351                 genDataPointerGet (left,result,ic);
8352                 return ;
8353         }
8354         
8355         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8356         aopOp (result,ic,FALSE);
8357         
8358         /* Check if can access directly instead of via a pointer */
8359         if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
8360                 direct = 1;
8361         }
8362
8363         /* If the pointer value is not in a the FSR then need to put it in */
8364         if (!AOP_INPREG(AOP(left)) && !direct) {
8365                 /* otherwise get a free pointer register */
8366                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8367                 if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */ 
8368                         emitpcode(POC_MOVLW, popGet(AOP(left),0));
8369                 else
8370                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
8371                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8372         }
8373         
8374         
8375 //      sym_link *etype;
8376         /* if bitfield then unpack the bits */
8377         if (IS_BITFIELD(retype)) 
8378                 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8379         else {
8380                 /* we have can just get the values */
8381                 int size = AOP_SIZE(result);
8382                 int offset = 0 ;  
8383                 
8384                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8385                 
8386                 while(size--) {
8387                         if (direct)
8388                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8389                         else
8390                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8391                         if (AOP_TYPE(result) == AOP_LIT) {
8392                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8393                         } else {
8394                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8395                         }
8396                         if (size && !direct)
8397                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8398                         offset++;
8399                 }
8400         }
8401         
8402         /* now some housekeeping stuff */
8403         if (aop) {
8404                 /* we had to allocate for this iCode */
8405                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8406                 freeAsmop(NULL,aop,ic,TRUE);
8407         } else { 
8408                 /* we did not allocate which means left
8409                 already in a pointer register, then
8410                 if size > 0 && this could be used again
8411                 we have to point it back to where it 
8412                 belongs */
8413                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8414                 if (AOP_SIZE(result) > 1 &&
8415                         !OP_SYMBOL(left)->remat &&
8416                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8417                         ic->depth )) {
8418                         int size = AOP_SIZE(result) - 1;
8419                         while (size--)
8420                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8421                 }
8422         }
8423         
8424         /* done */
8425         freeAsmop(left,NULL,ic,TRUE);
8426         freeAsmop(result,NULL,ic,TRUE);
8427
8428 }
8429
8430 /*-----------------------------------------------------------------*/
8431 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8432 /*-----------------------------------------------------------------*/
8433 static void genPagedPointerGet (operand *left, 
8434                                                                 operand *result, 
8435                                                                 iCode *ic)
8436 {
8437         asmop *aop = NULL;
8438         regs *preg = NULL ;
8439         char *rname ;
8440         sym_link *rtype, *retype;    
8441         
8442         FENTRY;
8443         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8444         
8445         rtype = operandType(result);
8446         retype= getSpec(rtype);
8447         
8448         aopOp(left,ic,FALSE);
8449         
8450         /* if the value is already in a pointer register
8451         then don't need anything more */
8452         if (!AOP_INPREG(AOP(left))) {
8453                 /* otherwise get a free pointer register */
8454                 aop = newAsmop(0);
8455                 preg = getFreePtr(ic,&aop,FALSE);
8456                 pic14_emitcode("mov","%s,%s",
8457                         preg->name,
8458                         aopGet(AOP(left),0,FALSE,TRUE));
8459                 rname = preg->name ;
8460         } else
8461                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8462         
8463         freeAsmop(left,NULL,ic,TRUE);
8464         aopOp (result,ic,FALSE);
8465         
8466         /* if bitfield then unpack the bits */
8467         if (IS_BITFIELD(retype)) 
8468                 genUnpackBits (result,left,rname,PPOINTER,0);
8469         else {
8470                 /* we have can just get the values */
8471                 int size = AOP_SIZE(result);
8472                 int offset = 0 ;  
8473                 
8474                 while (size--) {
8475                         
8476                         pic14_emitcode("movx","a,@%s",rname);
8477                         aopPut(AOP(result),"a",offset);
8478                         
8479                         offset++ ;
8480                         
8481                         if (size)
8482                                 pic14_emitcode("inc","%s",rname);
8483                 }
8484         }
8485         
8486         /* now some housekeeping stuff */
8487         if (aop) {
8488                 /* we had to allocate for this iCode */
8489                 freeAsmop(NULL,aop,ic,TRUE);
8490         } else { 
8491         /* we did not allocate which means left
8492         already in a pointer register, then
8493         if size > 0 && this could be used again
8494         we have to point it back to where it 
8495                 belongs */
8496                 if (AOP_SIZE(result) > 1 &&
8497                         !OP_SYMBOL(left)->remat &&
8498                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8499                         ic->depth )) {
8500                         int size = AOP_SIZE(result) - 1;
8501                         while (size--)
8502                                 pic14_emitcode("dec","%s",rname);
8503                 }
8504         }
8505         
8506         /* done */
8507         freeAsmop(result,NULL,ic,TRUE);
8508         
8509         
8510 }
8511
8512 /*-----------------------------------------------------------------*/
8513 /* genFarPointerGet - gget value from far space                    */
8514 /*-----------------------------------------------------------------*/
8515 static void genFarPointerGet (operand *left,
8516                                                           operand *result, iCode *ic)
8517 {
8518         int size, offset ;
8519         sym_link *retype = getSpec(operandType(result));
8520         
8521         FENTRY;
8522         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8523         
8524         aopOp(left,ic,FALSE);
8525         
8526         /* if the operand is already in dptr 
8527         then we do nothing else we move the value to dptr */
8528         if (AOP_TYPE(left) != AOP_STR) {
8529                 /* if this is remateriazable */
8530                 if (AOP_TYPE(left) == AOP_IMMD)
8531                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8532                 else { /* we need to get it byte by byte */
8533                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8534                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8535                         if (options.model == MODEL_FLAT24)
8536                         {
8537                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8538                         }
8539                 }
8540         }
8541         /* so dptr know contains the address */
8542         freeAsmop(left,NULL,ic,TRUE);
8543         aopOp(result,ic,FALSE);
8544         
8545         /* if bit then unpack */
8546         if (IS_BITFIELD(retype)) 
8547                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8548         else {
8549                 size = AOP_SIZE(result);
8550                 offset = 0 ;
8551                 
8552                 while (size--) {
8553                         pic14_emitcode("movx","a,@dptr");
8554                         aopPut(AOP(result),"a",offset++);
8555                         if (size)
8556                                 pic14_emitcode("inc","dptr");
8557                 }
8558         }
8559         
8560         freeAsmop(result,NULL,ic,TRUE);
8561 }
8562 #if 0
8563 /*-----------------------------------------------------------------*/
8564 /* genCodePointerGet - get value from code space                  */
8565 /*-----------------------------------------------------------------*/
8566 static void genCodePointerGet (operand *left,
8567                                                            operand *result, iCode *ic)
8568 {
8569         int size, offset ;
8570         sym_link *retype = getSpec(operandType(result));
8571         
8572         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8573         
8574         aopOp(left,ic,FALSE);
8575         
8576         /* if the operand is already in dptr 
8577         then we do nothing else we move the value to dptr */
8578         if (AOP_TYPE(left) != AOP_STR) {
8579                 /* if this is remateriazable */
8580                 if (AOP_TYPE(left) == AOP_IMMD)
8581                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8582                 else { /* we need to get it byte by byte */
8583                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8584                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8585                         if (options.model == MODEL_FLAT24)
8586                         {
8587                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8588                         }
8589                 }
8590         }
8591         /* so dptr know contains the address */
8592         freeAsmop(left,NULL,ic,TRUE);
8593         aopOp(result,ic,FALSE);
8594         
8595         /* if bit then unpack */
8596         if (IS_BITFIELD(retype)) 
8597                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8598         else {
8599                 size = AOP_SIZE(result);
8600                 offset = 0 ;
8601                 
8602                 while (size--) {
8603                         pic14_emitcode("clr","a");
8604                         pic14_emitcode("movc","a,@a+dptr");
8605                         aopPut(AOP(result),"a",offset++);
8606                         if (size)
8607                                 pic14_emitcode("inc","dptr");
8608                 }
8609         }
8610         
8611         freeAsmop(result,NULL,ic,TRUE);
8612 }
8613 #endif
8614 /*-----------------------------------------------------------------*/
8615 /* genGenPointerGet - gget value from generic pointer space        */
8616 /*-----------------------------------------------------------------*/
8617 static void genGenPointerGet (operand *left,
8618                                                           operand *result, iCode *ic)
8619 {
8620         int size, offset ;
8621         sym_link *retype = getSpec(operandType(result));
8622         
8623         FENTRY;
8624         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8625         aopOp(left,ic,FALSE);
8626         aopOp(result,ic,FALSE);
8627         
8628         
8629         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8630         
8631         /* if the operand is already in dptr 
8632         then we do nothing else we move the value to dptr */
8633         //  if (AOP_TYPE(left) != AOP_STR) {
8634         /* if this is remateriazable */
8635         if (AOP_TYPE(left) == AOP_IMMD) {
8636                 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8637                 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8638         }
8639         else { /* we need to get it byte by byte */
8640                 
8641                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8642                 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8643                 
8644                 size = AOP_SIZE(result);
8645                 offset = 0 ;
8646                 
8647                 while(size--) {
8648                         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8649                         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8650                         if(size)
8651                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8652                 }
8653                 goto release;
8654         }
8655         //}
8656         /* so dptr know contains the address */
8657         
8658         /* if bit then unpack */
8659         //if (IS_BITFIELD(retype)) 
8660         //  genUnpackBits(result,"dptr",GPOINTER);
8661         
8662 release:
8663         freeAsmop(left,NULL,ic,TRUE);
8664         freeAsmop(result,NULL,ic,TRUE);
8665         
8666 }
8667
8668 /*-----------------------------------------------------------------*/
8669 /* genConstPointerGet - get value from const generic pointer space */
8670 /*-----------------------------------------------------------------*/
8671 static void genConstPointerGet (operand *left,
8672                                                                 operand *result, iCode *ic)
8673 {
8674         //sym_link *retype = getSpec(operandType(result));
8675         symbol *albl, *blbl;//, *clbl;
8676         PIC_OPCODE poc;
8677         int i, size, lit;
8678         pCodeOp *pcop;
8679         
8680         FENTRY;
8681         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8682         aopOp(left,ic,FALSE);
8683         aopOp(result,ic,FALSE);
8684         
8685         size = AOP_SIZE(result);
8686         
8687         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8688         
8689         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8690
8691         lit = aop_isLitLike (AOP(left));
8692         poc = lit ? POC_MOVLW : POC_MOVFW;
8693
8694         if (lit)
8695         {
8696                 for (i = 0; i < size; i++)
8697                 {
8698                         albl = newiTempLabel(NULL);
8699                         blbl = newiTempLabel(NULL);
8700                         
8701                         emitpcode(POC_CALL,popGetLabel(albl->key));
8702                         pcop = popGetLabel(blbl->key);
8703                         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8704                         emitpcode(POC_GOTO,pcop);
8705                         
8706                         emitpLabel(albl->key);
8707                         emitpcode(poc,popGetAddr(AOP(left),1,i));
8708                         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8709                         emitpcode(poc,popGetAddr(AOP(left),0,i));
8710                         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8711                 
8712                         emitpLabel(blbl->key);
8713                         emitpcode(POC_MOVWF,popGet(AOP(result),i));
8714                 } // for
8715         } else {
8716                 albl = newiTempLabel(NULL);
8717                 blbl = newiTempLabel(NULL);
8718                 //clbl = newiTempLabel(NULL);
8719
8720                 emitpcode (POC_GOTO, popGetLabel (blbl->key));
8721                 
8722                 emitpLabel(albl->key);
8723                 emitpcode(poc,popGet(AOP(left),1));
8724                 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8725                 emitpcode(poc,popGet(AOP(left),0));
8726                 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8727                 
8728                 emitpLabel(blbl->key);
8729                 
8730                 for (i = 0; i < size; i++)
8731                 {
8732                         emitpcode(POC_CALL,popGetLabel(albl->key));
8733                         /* the next two instructions (plus clbl) might be useless... */
8734                         //pcop = popGetLabel(clbl->key);
8735                         //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8736                         //emitpcode(POC_GOTO,pcop);
8737                         //emitpLabel(clbl->key);
8738
8739                         if (i+1 < size) {
8740                                 emitpcode (POC_INCF, popGet (AOP(left), 0));
8741                                 emitSKPNZ;
8742                                 emitpcode (POC_INCF, popGet (AOP(left), 1));
8743                         }
8744                         emitpcode(POC_MOVWF,popGet(AOP(result),i));
8745                 } // for
8746                 if (size > 1) {
8747                         /* restore left's value */
8748                         emitpcode (POC_MOVLW, popGetLit (size-1));
8749                         emitpcode (POC_SUBWF, popGet (AOP(left), 0));
8750                         emitSKPC;
8751                         emitpcode (POC_DECF, popGet (AOP(left), 1));
8752                 } // if
8753         } // if (lit)
8754         
8755         freeAsmop(left,NULL,ic,TRUE);
8756         freeAsmop(result,NULL,ic,TRUE);
8757         
8758 }
8759 /*-----------------------------------------------------------------*/
8760 /* genPointerGet - generate code for pointer get                   */
8761 /*-----------------------------------------------------------------*/
8762 static void genPointerGet (iCode *ic)
8763 {
8764         operand *left, *result ;
8765         sym_link *type, *etype;
8766         int p_type = -1;
8767         
8768         FENTRY;
8769         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8770         
8771         left = IC_LEFT(ic);
8772         result = IC_RESULT(ic) ;
8773         
8774         /* depending on the type of pointer we need to
8775         move it to the correct pointer register */
8776         type = operandType(left);
8777         etype = getSpec(type);
8778         
8779         if (IS_PTR_CONST(type))
8780                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
8781         
8782         /* if left is of type of pointer then it is simple */
8783         if (IS_PTR(type) && !IS_FUNC(type->next)) 
8784                 p_type = DCL_TYPE(type);
8785         else {
8786                 /* we have to go by the storage class */
8787                 p_type = PTR_TYPE(SPEC_OCLS(etype));
8788                 
8789                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8790                 
8791                 if (SPEC_OCLS(etype)->codesp ) {
8792                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
8793                         //p_type = CPOINTER ; 
8794                 }
8795                 else
8796                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8797                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
8798                         /*p_type = FPOINTER ;*/ 
8799                         else
8800                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8801                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
8802                                 /*        p_type = PPOINTER; */
8803                                 else
8804                                         if (SPEC_OCLS(etype) == idata )
8805                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
8806                                         /*      p_type = IPOINTER; */
8807                                         else
8808                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
8809                                         /*      p_type = POINTER ; */
8810         }
8811         
8812         /* now that we have the pointer type we assign
8813         the pointer values */
8814         switch (p_type) {
8815                 
8816         case POINTER: 
8817         case IPOINTER:
8818                 genNearPointerGet (left,result,ic);
8819                 break;
8820                 
8821         case PPOINTER:
8822                 genPagedPointerGet(left,result,ic);
8823                 break;
8824                 
8825         case FPOINTER:
8826                 genFarPointerGet (left,result,ic);
8827                 break;
8828                 
8829         case CPOINTER:
8830                 genConstPointerGet (left,result,ic);
8831                 //pic14_emitcodePointerGet (left,result,ic);
8832                 break;
8833                 
8834         case GPOINTER:
8835                 if (IS_CODEPTR(type) || IS_PTR_CONST(type) || SPEC_CONST(etype))
8836                         genConstPointerGet (left,result,ic);
8837                 else
8838                         genGenPointerGet (left,result,ic);
8839                 break;
8840         default:
8841                 assert ( !"unhandled pointer type" );
8842                 break;
8843         }
8844         
8845 }
8846
8847 /*-----------------------------------------------------------------*/
8848 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into  */
8849 /* A through a pointer register (R0, R1, or DPTR). The original    */
8850 /* value of A can be preserved in B.                               */
8851 /* PIC has to use INDF register.                                   */
8852 /*-----------------------------------------------------------------*/
8853 static void
8854 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8855 {
8856     FENTRY;
8857     switch (p_type)
8858     {
8859     case IPOINTER:
8860     case POINTER:
8861                 if (preserveAinB)
8862                         pic14_emitcode ("mov", "b,a");
8863 //              pic14_emitcode ("mov", "a,@%s", rname);
8864                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8865                 break;
8866                 
8867     case PPOINTER:
8868                 if (preserveAinB)
8869                         pic14_emitcode ("mov", "b,a");
8870                 pic14_emitcode ("movx", "a,@%s", rname);
8871                 break;
8872                 
8873     case FPOINTER:
8874                 if (preserveAinB)
8875                         pic14_emitcode ("mov", "b,a");
8876                 pic14_emitcode ("movx", "a,@dptr");
8877                 break;
8878                 
8879     case CPOINTER:
8880                 if (preserveAinB)
8881                         pic14_emitcode ("mov", "b,a");
8882                 pic14_emitcode ("clr", "a");
8883                 pic14_emitcode ("movc", "a,@a+dptr");
8884                 break;
8885                 
8886     case GPOINTER:
8887                 if (preserveAinB)
8888         {
8889                         pic14_emitcode ("push", "b");
8890                         pic14_emitcode ("push", "acc");
8891         }
8892                 pic14_emitcode ("lcall", "__gptrget");
8893                 if (preserveAinB)
8894                         pic14_emitcode ("pop", "b");
8895                 break;
8896     }
8897 }
8898
8899 /*-----------------------------------------------------------------*/
8900 /* emitPtrByteSet - emits code to set a byte from src through a    */
8901 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8902 /*-----------------------------------------------------------------*/
8903 static void
8904 emitPtrByteSet (char *rname, int p_type, char *src)
8905 {
8906     FENTRY;
8907     switch (p_type)
8908     {
8909     case IPOINTER:
8910     case POINTER:
8911                 if (*src=='@')
8912         {
8913                         MOVA (src);
8914                         pic14_emitcode ("mov", "@%s,a", rname);
8915         }
8916                 else
8917 //                      pic14_emitcode ("mov", "@%s,%s", rname, src);
8918                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
8919                 break;
8920                 
8921     case PPOINTER:
8922                 MOVA (src);
8923                 pic14_emitcode ("movx", "@%s,a", rname);
8924                 break;
8925                 
8926     case FPOINTER:
8927                 MOVA (src);
8928                 pic14_emitcode ("movx", "@dptr,a");
8929                 break;
8930                 
8931     case GPOINTER:
8932                 MOVA (src);
8933                 pic14_emitcode ("lcall", "__gptrput");
8934                 break;
8935     }
8936 }
8937
8938 /*-----------------------------------------------------------------*/
8939 /* genPackBits - generates code for packed bit storage             */
8940 /*-----------------------------------------------------------------*/
8941 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
8942 {
8943         int offset = 0;       /* source byte offset */
8944         int rlen = 0;         /* remaining bitfield length */
8945         int blen;             /* bitfield length */
8946         int bstr;             /* bitfield starting bit within byte */
8947         int litval;           /* source literal value (if AOP_LIT) */
8948         unsigned char mask;   /* bitmask within current byte */
8949
8950         FENTRY;
8951         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8952         
8953         blen = SPEC_BLEN (etype);
8954         bstr = SPEC_BSTR (etype);
8955         
8956         /* If the bitfield length is less than a byte */
8957         if (blen < 8)
8958     {
8959                 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8960                         (unsigned char) (0xFF >> (8 - bstr)));
8961                 
8962                 if (AOP_TYPE (right) == AOP_LIT)
8963         {
8964                         /* Case with a bitfield length <8 and literal source
8965                         */
8966                         int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8967                         if (blen == 1) {
8968                                 if (p_type == -1) {
8969                                         pCodeOp *pcop;
8970                                         if (AOP(result)->type == AOP_PCODE)
8971                                                 pcop = newpCodeOpBit(AOP(result)->aopu.pcop->name,bstr,0);
8972                                         else
8973                                                 pcop = popGet(AOP(result),0);
8974                                         emitpcode(lit?POC_BSF:POC_BCF,pcop);
8975                                 } else {
8976                                         emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
8977                                 }
8978                                 return;
8979                         } else {
8980                                 litval = lit << bstr;
8981                                 litval &= (~mask) & 0xff;
8982                                 if (p_type == -1)
8983                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
8984                                 else
8985                                         emitPtrByteGet (rname, p_type, FALSE);
8986                                 if ((mask|litval)!=0xff)
8987                                         emitpcode(POC_ANDLW,popGetLit(mask));
8988                                 if (litval)
8989                                         emitpcode(POC_IORLW,popGetLit(litval));
8990                         }
8991         }
8992                 else
8993         {
8994                         if (blen==1) {
8995                                 if (p_type == -1) {
8996                                         /* 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 */
8997                                         emitpcode(POC_RLF,popGet(AOP(right),0));
8998                                         emitSKPC;
8999                                         emitpcode(POC_BCF,popGet(AOP(result),0));
9000                                         emitSKPNC;
9001                                         emitpcode(POC_BSF,popGet(AOP(result),0));
9002                                 } else if (p_type!=GPOINTER) {
9003                                         /* Case with a bitfield length == 1 and no generic pointer
9004                                         */
9005                                         if (AOP_TYPE (right) == AOP_CRY)
9006                                                 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9007                                         else
9008                                         {
9009                                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9010                                                 pic14_emitcode ("rrc","a");
9011                                         }
9012                                         emitPtrByteGet (rname, p_type, FALSE);
9013                                         pic14_emitcode ("mov","acc.%d,c",bstr);
9014                                 }
9015             }
9016                         else
9017             {
9018                                 //bool pushedB;
9019                                 /* Case with a bitfield length < 8 and arbitrary source
9020                                 */
9021                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9022                                 /* shift and mask source value */
9023                                 AccLsh (right,0,bstr);
9024                                 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9025                                 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
9026                                 
9027                                 //pushedB = pushB ();
9028                                 if (p_type == -1)
9029                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9030                                 else
9031                                         emitPtrByteGet (rname, p_type, TRUE);
9032                                 
9033                                 pic14_emitcode ("anl", "a,#0x%02x", mask);
9034                                 pic14_emitcode ("orl", "a,b");
9035                                 emitpcode(POC_ANDLW,popGetLit(mask));
9036                                 emitpcode(POC_IORFW,popGet(AOP(right),0));
9037                                 if (p_type == GPOINTER)
9038                                         pic14_emitcode ("pop", "b");
9039                                 
9040                                 //popB (pushedB);
9041                         }
9042         }
9043                 
9044                 if (p_type == -1)
9045                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9046                 else
9047                         emitPtrByteSet (rname, p_type, "a");
9048                 return;
9049     }
9050         
9051         /* Bit length is greater than 7 bits. In this case, copy  */
9052         /* all except the partial byte at the end                 */
9053         for (rlen=blen;rlen>=8;rlen-=8)
9054     {
9055                 emitPtrByteSet (rname, p_type,
9056                         aopGet (AOP (right), offset++, FALSE, TRUE) );
9057                 if (rlen>8)
9058                         pic14_emitcode ("inc", "%s", rname);
9059     }
9060         
9061         /* If there was a partial byte at the end */
9062         if (rlen)
9063     {
9064                 mask = (((unsigned char) -1 << rlen) & 0xff);
9065                 
9066                 if (AOP_TYPE (right) == AOP_LIT)
9067         {
9068                 /* Case with partial byte and literal source
9069                         */
9070                         litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9071                         litval >>= (blen-rlen);
9072                         litval &= (~mask) & 0xff;
9073                         emitPtrByteGet (rname, p_type, FALSE);
9074                         if ((mask|litval)!=0xff)
9075                                 pic14_emitcode ("anl","a,#0x%02x", mask);
9076                         if (litval)
9077                                 pic14_emitcode ("orl","a,#0x%02x", litval);
9078         }
9079                 else
9080         {
9081                         //bool pushedB;
9082                         /* Case with partial byte and arbitrary source
9083                         */
9084                         MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9085                         pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9086                         
9087                         //pushedB = pushB ();
9088                         /* transfer A to B and get next byte */
9089                         emitPtrByteGet (rname, p_type, TRUE);
9090                         
9091                         pic14_emitcode ("anl", "a,#0x%02x", mask);
9092                         pic14_emitcode ("orl", "a,b");
9093                         if (p_type == GPOINTER)
9094                                 pic14_emitcode ("pop", "b");
9095                         
9096                         //popB (pushedB);
9097         }
9098                 emitPtrByteSet (rname, p_type, "a");
9099     }
9100         
9101 }
9102
9103 /*-----------------------------------------------------------------*/
9104 /* SetIrp - Set IRP bit                                            */
9105 /*-----------------------------------------------------------------*/
9106 void SetIrp(operand *result) {
9107         FENTRY;
9108         if (AOP_TYPE(result) == AOP_LIT) {
9109                 unsigned lit = (unsigned)operandLitValue(result);
9110                 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9111         } else {
9112                 if (PCOP(AOP(result))->type == PO_LITERAL) {
9113                         int addrs = PCOL(AOP(result))->lit;
9114                         emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9115                 } else {
9116                         emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
9117                         if(AOP_SIZE(result) > 1) {
9118                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9119                                 emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9120                         }
9121                 }
9122         }
9123 }
9124
9125 /*-----------------------------------------------------------------*/
9126 /* genDataPointerSet - remat pointer to data space                 */
9127 /*-----------------------------------------------------------------*/
9128 static void genDataPointerSet(operand *right,
9129         operand *result,
9130         iCode *ic)
9131 {
9132         int size, offset = 0 ;
9133         char *l, buffer[256];
9134         
9135         FENTRY;
9136         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9137         aopOp(right,ic,FALSE);
9138         
9139         l = aopGet(AOP(result),0,FALSE,TRUE);
9140         size = AOP_SIZE(right);
9141         /*
9142         if ( AOP_TYPE(result) == AOP_PCODE) {
9143         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9144         AOP(result)->aopu.pcop->name,
9145         PCOI(AOP(result)->aopu.pcop)->offset);
9146         }
9147         */
9148         
9149         // tsd, was l+1 - the underline `_' prefix was being stripped
9150         while (size--) {
9151                 emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
9152                 if (offset) {
9153                         sprintf(buffer,"(%s + %d)",l,offset);
9154                         fprintf(stderr,"%s:%i: oops  %s (%i, AOP_LIT=%i)\n",__FILE__,__LINE__,buffer, AOP_TYPE(right), AOP_LIT);
9155                 } else
9156                         sprintf(buffer,"%s",l);
9157                 
9158                 if (AOP_TYPE(right) == AOP_LIT) {
9159                         unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9160                         lit = lit >> (8*offset);
9161                         if(lit&0xff) {
9162                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9163                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9164                         } else {
9165                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9166                         }
9167                 } else {
9168                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9169                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9170                 }
9171                 
9172                 offset++;
9173         }
9174         
9175         freeAsmop(right,NULL,ic,TRUE);
9176         freeAsmop(result,NULL,ic,TRUE);
9177 }
9178
9179 /*-----------------------------------------------------------------*/
9180 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9181 /*-----------------------------------------------------------------*/
9182 static void genNearPointerSet (operand *right,
9183                                                            operand *result, 
9184                                                            iCode *ic)
9185 {
9186         asmop *aop = NULL;
9187         sym_link *ptype = operandType(result);
9188         sym_link *retype = getSpec(operandType(right));
9189         sym_link *letype = getSpec(ptype);
9190         int direct = 0;
9191         
9192         
9193         FENTRY;
9194         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9195         aopOp(result,ic,FALSE);
9196         
9197         
9198         /* if the result is rematerializable &
9199         in data space & not a bit variable */
9200         //if (AOP_TYPE(result) == AOP_IMMD &&
9201         if (AOP_TYPE(result) == AOP_PCODE &&
9202                 DCL_TYPE(ptype) == POINTER   &&
9203                 !IS_BITVAR (retype) &&
9204                 !IS_BITVAR (letype)) {
9205                 genDataPointerSet (right,result,ic);
9206                 freeAsmop(result,NULL,ic,TRUE);
9207                 return;
9208         }
9209
9210         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9211         aopOp(right,ic,FALSE);
9212         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9213         
9214         /* Check if can access directly instead of via a pointer */
9215         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9216                 direct = 1;
9217         }
9218
9219         /* If the pointer value is not in a the FSR then need to put it in */
9220         if (!AOP_INPREG(AOP(result)) && !direct) {
9221                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9222                 if (PCOP(AOP(result))->type == PO_LITERAL) 
9223                         emitpcode(POC_MOVLW, popGet(AOP(result),0));
9224                 else
9225                         emitpcode(POC_MOVFW, popGet(AOP(result),0));
9226                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
9227         }
9228
9229         /* Must set/reset IRP bit for use with FSR. */
9230         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9231         if (!direct)
9232                 SetIrp(result);
9233
9234         /* if bitfield then unpack the bits */
9235         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9236                 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
9237         } else {
9238                 /* we have can just get the values */
9239                 int size = AOP_SIZE(right);
9240                 int offset = 0 ;    
9241                 
9242                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9243                 while (size--) {
9244                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9245                         if (*l == '@' ) {
9246                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9247                         } else {
9248                                 if (AOP_TYPE(right) == AOP_LIT) {
9249                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9250                                 } else {
9251                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9252                                 }
9253                                 if (direct)
9254                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9255                                 else
9256                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9257                         }
9258                         if (size && !direct)
9259                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9260                         offset++;
9261                 }
9262         }
9263         
9264         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9265         /* now some housekeeping stuff */
9266         if (aop) {
9267                 /* we had to allocate for this iCode */
9268                 freeAsmop(NULL,aop,ic,TRUE);
9269         } else { 
9270                 /* we did not allocate which means left
9271                 already in a pointer register, then
9272                 if size > 0 && this could be used again
9273                 we have to point it back to where it 
9274                 belongs */
9275                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9276                 if (AOP_SIZE(right) > 1 &&
9277                         !OP_SYMBOL(result)->remat &&
9278                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9279                         ic->depth )) {
9280                         int size = AOP_SIZE(right) - 1;
9281                         while (size--)
9282                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9283                 }
9284         }
9285         
9286         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9287         /* done */
9288
9289         freeAsmop(right,NULL,ic,TRUE);
9290         freeAsmop(result,NULL,ic,TRUE);
9291 }
9292
9293 /*-----------------------------------------------------------------*/
9294 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9295 /*-----------------------------------------------------------------*/
9296 static void genPagedPointerSet (operand *right,
9297                                                                 operand *result, 
9298                                                                 iCode *ic)
9299 {
9300         asmop *aop = NULL;
9301         regs *preg = NULL ;
9302         char *rname , *l;
9303         sym_link *retype;
9304         
9305         FENTRY;
9306         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9307         
9308         retype= getSpec(operandType(right));
9309         
9310         aopOp(result,ic,FALSE);
9311         
9312         /* if the value is already in a pointer register
9313         then don't need anything more */
9314         if (!AOP_INPREG(AOP(result))) {
9315                 /* otherwise get a free pointer register */
9316                 aop = newAsmop(0);
9317                 preg = getFreePtr(ic,&aop,FALSE);
9318                 pic14_emitcode("mov","%s,%s",
9319                         preg->name,
9320                         aopGet(AOP(result),0,FALSE,TRUE));
9321                 rname = preg->name ;
9322         } else
9323                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9324         
9325         freeAsmop(result,NULL,ic,TRUE);
9326         aopOp (right,ic,FALSE);
9327         
9328         /* if bitfield then unpack the bits */
9329         if (IS_BITFIELD(retype)) 
9330                 genPackBits (retype,result,right,rname,PPOINTER);
9331         else {
9332                 /* we have can just get the values */
9333                 int size = AOP_SIZE(right);
9334                 int offset = 0 ;  
9335                 
9336                 while (size--) {
9337                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9338                         
9339                         MOVA(l);
9340                         pic14_emitcode("movx","@%s,a",rname);
9341                         
9342                         if (size)
9343                                 pic14_emitcode("inc","%s",rname);
9344                         
9345                         offset++;
9346                 }
9347         }
9348         
9349         /* now some housekeeping stuff */
9350         if (aop) {
9351                 /* we had to allocate for this iCode */
9352                 freeAsmop(NULL,aop,ic,TRUE);
9353         } else { 
9354         /* we did not allocate which means left
9355         already in a pointer register, then
9356         if size > 0 && this could be used again
9357         we have to point it back to where it 
9358                 belongs */
9359                 if (AOP_SIZE(right) > 1 &&
9360                         !OP_SYMBOL(result)->remat &&
9361                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9362                         ic->depth )) {
9363                         int size = AOP_SIZE(right) - 1;
9364                         while (size--)
9365                                 pic14_emitcode("dec","%s",rname);
9366                 }
9367         }
9368         
9369         /* done */
9370         freeAsmop(right,NULL,ic,TRUE);
9371         
9372         
9373 }
9374
9375 /*-----------------------------------------------------------------*/
9376 /* genFarPointerSet - set value from far space                     */
9377 /*-----------------------------------------------------------------*/
9378 static void genFarPointerSet (operand *right,
9379                                                           operand *result, iCode *ic)
9380 {
9381         int size, offset ;
9382         sym_link *retype = getSpec(operandType(right));
9383         
9384         FENTRY;
9385         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9386         aopOp(result,ic,FALSE);
9387         
9388         /* if the operand is already in dptr 
9389         then we do nothing else we move the value to dptr */
9390         if (AOP_TYPE(result) != AOP_STR) {
9391                 /* if this is remateriazable */
9392                 if (AOP_TYPE(result) == AOP_IMMD)
9393                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9394                 else { /* we need to get it byte by byte */
9395                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9396                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9397                         if (options.model == MODEL_FLAT24)
9398                         {
9399                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9400                         }
9401                 }
9402         }
9403         /* so dptr know contains the address */
9404         freeAsmop(result,NULL,ic,TRUE);
9405         aopOp(right,ic,FALSE);
9406         
9407         /* if bit then unpack */
9408         if (IS_BITFIELD(retype)) 
9409                 genPackBits(retype,result,right,"dptr",FPOINTER);
9410         else {
9411                 size = AOP_SIZE(right);
9412                 offset = 0 ;
9413                 
9414                 while (size--) {
9415                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9416                         MOVA(l);
9417                         pic14_emitcode("movx","@dptr,a");
9418                         if (size)
9419                                 pic14_emitcode("inc","dptr");
9420                 }
9421         }
9422         
9423         freeAsmop(right,NULL,ic,TRUE);
9424 }
9425
9426 /*-----------------------------------------------------------------*/
9427 /* genGenPointerSet - set value from generic pointer space         */
9428 /*-----------------------------------------------------------------*/
9429 static void genGenPointerSet (operand *right,
9430                                                           operand *result, iCode *ic)
9431 {
9432         sym_link *ptype = operandType(result);
9433         sym_link *retype = getSpec(operandType(right));
9434         sym_link *letype = getSpec (ptype);
9435         
9436         FENTRY;
9437         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9438         
9439         aopOp(result,ic,FALSE);
9440         aopOp(right,ic,FALSE);
9441         
9442         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9443         
9444         /* if the operand is already in dptr 
9445         then we do nothing else we move the value to dptr */
9446         if (AOP_TYPE(result) != AOP_STR) {
9447                 /* if this is remateriazable */
9448                 if (AOP_TYPE(result) == AOP_IMMD) {
9449                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9450                         pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9451                 }
9452                 else {
9453                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9454                         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9455
9456                         /* Must set/reset IRP bit for use with FSR. */
9457                         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9458                         SetIrp(result);
9459                 }
9460         }
9461
9462         /* if bitfield then unpack the bits */
9463         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9464                 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9465         } else {
9466                 /* we have can just get the values */
9467                 int size = AOP_SIZE(right);
9468                 int offset = 0 ;    
9469                 
9470                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9471                 while (size--) {
9472                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9473                         if (*l == '@' ) {
9474                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9475                         } else {
9476                                 if (AOP_TYPE(right) == AOP_LIT) {
9477                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9478                                 } else {
9479                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9480                                 }
9481                                 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9482                         }
9483                         if (size)
9484                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9485                         offset++;
9486                 }
9487         }
9488         
9489         freeAsmop(right,NULL,ic,TRUE);
9490         freeAsmop(result,NULL,ic,TRUE);
9491 }
9492
9493 /*-----------------------------------------------------------------*/
9494 /* genPointerSet - stores the value into a pointer location        */
9495 /*-----------------------------------------------------------------*/
9496 static void genPointerSet (iCode *ic)
9497 {    
9498         operand *right, *result ;
9499         sym_link *type, *etype;
9500         int p_type;
9501         
9502         FENTRY;
9503         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9504         
9505         right = IC_RIGHT(ic);
9506         result = IC_RESULT(ic) ;
9507         
9508         /* depending on the type of pointer we need to
9509         move it to the correct pointer register */
9510         type = operandType(result);
9511         etype = getSpec(type);
9512         /* if left is of type of pointer then it is simple */
9513         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9514                 p_type = DCL_TYPE(type);
9515         }
9516         else {
9517                 /* we have to go by the storage class */
9518                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9519                 
9520                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9521                 /*      p_type = CPOINTER ;  */
9522                 /*  } */
9523                 /*  else */
9524                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9525                 /*    p_type = FPOINTER ; */
9526                 /*      else */
9527                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9528                 /*        p_type = PPOINTER ; */
9529                 /*    else */
9530                 /*        if (SPEC_OCLS(etype) == idata ) */
9531                 /*      p_type = IPOINTER ; */
9532                 /*        else */
9533                 /*      p_type = POINTER ; */
9534         }
9535         
9536         /* now that we have the pointer type we assign
9537         the pointer values */
9538         switch (p_type) {
9539                 
9540         case POINTER:
9541         case IPOINTER:
9542                 genNearPointerSet (right,result,ic);
9543                 break;
9544                 
9545         case PPOINTER:
9546                 genPagedPointerSet (right,result,ic);
9547                 break;
9548                 
9549         case FPOINTER:
9550                 genFarPointerSet (right,result,ic);
9551                 break;
9552                 
9553         case GPOINTER:
9554                 genGenPointerSet (right,result,ic);
9555                 break;
9556                 
9557         default:
9558                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9559                         "genPointerSet: illegal pointer type");
9560         }
9561 }
9562
9563 /*-----------------------------------------------------------------*/
9564 /* genIfx - generate code for Ifx statement                        */
9565 /*-----------------------------------------------------------------*/
9566 static void genIfx (iCode *ic, iCode *popIc)
9567 {
9568         operand *cond = IC_COND(ic);
9569         int isbit =0;
9570         
9571         FENTRY;
9572         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9573         
9574         aopOp(cond,ic,FALSE);
9575         
9576         /* get the value into acc */
9577         if (AOP_TYPE(cond) != AOP_CRY)
9578                 pic14_toBoolean(cond);
9579         else
9580                 isbit = 1;
9581         /* the result is now in the accumulator */
9582         freeAsmop(cond,NULL,ic,TRUE);
9583         
9584         /* if there was something to be popped then do it */
9585         if (popIc)
9586                 genIpop(popIc);
9587         
9588         /* if the condition is  a bit variable */
9589         if (isbit && IS_ITEMP(cond) && 
9590                 SPIL_LOC(cond)) {
9591                 genIfxJump(ic,SPIL_LOC(cond)->rname);
9592                 DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9593         }
9594         else {
9595                 if (isbit && !IS_ITEMP(cond))
9596                         genIfxJump(ic,OP_SYMBOL(cond)->rname);
9597                 else
9598                         genIfxJump(ic,"a");
9599         }
9600         ic->generated = 1;
9601         
9602 }
9603
9604 /*-----------------------------------------------------------------*/
9605 /* genAddrOf - generates code for address of                       */
9606 /*-----------------------------------------------------------------*/
9607 static void genAddrOf (iCode *ic)
9608 {
9609         operand *right, *result, *left;
9610         int size, offset ;
9611         
9612         FENTRY;
9613         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9614         
9615         
9616         //aopOp(IC_RESULT(ic),ic,FALSE);
9617         
9618         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9619         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9620         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9621         
9622         DEBUGpic14_AopType(__LINE__,left,right,result);
9623         assert (IS_SYMOP (left));
9624         
9625         /* sanity check: generic pointers to code space are not yet supported,
9626          * pionters to codespace must not be assigned addresses of __data values. */
9627  #if 0
9628         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9629         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)));
9630         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)));
9631         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)));
9632         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)));
9633 #endif
9634
9635         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9636           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9637                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9638                 OP_SYMBOL(left)->name);
9639         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9640           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9641                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9642                 OP_SYMBOL(left)->name);
9643         }
9644         
9645         size = AOP_SIZE(IC_RESULT(ic));
9646         offset = 0;
9647         
9648         while (size--) {
9649                 /* fixing bug #863624, reported from (errolv) */
9650                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9651                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9652                 
9653 #if 0
9654                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9655                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9656 #endif
9657                 offset++;
9658         }
9659         
9660         freeAsmop(left,NULL,ic,FALSE);
9661         freeAsmop(result,NULL,ic,TRUE);
9662         
9663 }
9664
9665 #if 0
9666 /*-----------------------------------------------------------------*/
9667 /* genFarFarAssign - assignment when both are in far space         */
9668 /*-----------------------------------------------------------------*/
9669 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9670 {
9671         int size = AOP_SIZE(right);
9672         int offset = 0;
9673         char *l ;
9674         /* first push the right side on to the stack */
9675         while (size--) {
9676                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9677                 MOVA(l);
9678                 pic14_emitcode ("push","acc");
9679         }
9680         
9681         freeAsmop(right,NULL,ic,FALSE);
9682         /* now assign DPTR to result */
9683         aopOp(result,ic,FALSE);
9684         size = AOP_SIZE(result);
9685         while (size--) {
9686                 pic14_emitcode ("pop","acc");
9687                 aopPut(AOP(result),"a",--offset);
9688         }
9689         freeAsmop(result,NULL,ic,FALSE);
9690         
9691 }
9692 #endif
9693
9694 /*-----------------------------------------------------------------*/
9695 /* genAssign - generate code for assignment                        */
9696 /*-----------------------------------------------------------------*/
9697 static void genAssign (iCode *ic)
9698 {
9699         operand *result, *right;
9700         int size, offset,know_W;
9701         unsigned long lit = 0L;
9702         
9703         result = IC_RESULT(ic);
9704         right  = IC_RIGHT(ic) ;
9705         
9706         FENTRY;
9707         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9708         
9709         /* if they are the same */
9710         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9711                 return ;
9712         
9713         aopOp(right,ic,FALSE);
9714         aopOp(result,ic,TRUE);
9715         
9716         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9717         
9718         /* if they are the same registers */
9719         if (pic14_sameRegs(AOP(right),AOP(result)))
9720                 goto release;
9721
9722         /* special case: assign from __code */
9723         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9724                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9725                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9726                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9727                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9728         {
9729           emitpComment ("genAssign from CODESPACE");
9730           genConstPointerGet (right, result, ic);
9731           goto release;
9732         }
9733         
9734         /* just for symmetry reasons... */
9735         if (!IS_ITEMP(result)
9736                 && IS_SYMOP (result)
9737                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9738         {
9739           assert ( !"cannot write to CODESPACE" );
9740         }
9741
9742         /* if the result is a bit */
9743         if (AOP_TYPE(result) == AOP_CRY) {
9744                 
9745         /* if the right size is a literal then
9746                 we know what the value is */
9747                 if (AOP_TYPE(right) == AOP_LIT) {
9748                         
9749                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9750                                 popGet(AOP(result),0));
9751                         
9752                         if (((int) operandLitValue(right))) 
9753                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9754                                 AOP(result)->aopu.aop_dir,
9755                                 AOP(result)->aopu.aop_dir);
9756                         else
9757                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9758                                 AOP(result)->aopu.aop_dir,
9759                                 AOP(result)->aopu.aop_dir);
9760                         goto release;
9761                 }
9762                 
9763                 /* the right is also a bit variable */
9764                 if (AOP_TYPE(right) == AOP_CRY) {
9765                         emitpcode(POC_BCF,    popGet(AOP(result),0));
9766                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
9767                         emitpcode(POC_BSF,    popGet(AOP(result),0));
9768                         
9769                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
9770                                 AOP(result)->aopu.aop_dir,
9771                                 AOP(result)->aopu.aop_dir);
9772                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
9773                                 AOP(right)->aopu.aop_dir,
9774                                 AOP(right)->aopu.aop_dir);
9775                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
9776                                 AOP(result)->aopu.aop_dir,
9777                                 AOP(result)->aopu.aop_dir);
9778                         goto release ;
9779                 }
9780                 
9781                 /* we need to or */
9782                 emitpcode(POC_BCF,    popGet(AOP(result),0));
9783                 pic14_toBoolean(right);
9784                 emitSKPZ;
9785                 emitpcode(POC_BSF,    popGet(AOP(result),0));
9786                 //aopPut(AOP(result),"a",0);
9787                 goto release ;
9788         }
9789         
9790         /* bit variables done */
9791         /* general case */
9792         size = AOP_SIZE(result);
9793         offset = 0 ;
9794         if(AOP_TYPE(right) == AOP_LIT)
9795                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9796         
9797         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9798                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9799                 if(aopIdx(AOP(result),0) == 4) {
9800                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9801                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9802                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9803                         goto release;
9804                 } else
9805                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9806         }
9807         
9808         know_W=-1;
9809         while (size--) {
9810                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9811                 if(AOP_TYPE(right) == AOP_LIT) {
9812                         if(lit&0xff) {
9813                                 if(know_W != (int)(lit&0xff))
9814                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
9815                                 know_W = lit&0xff;
9816                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9817                         } else
9818                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9819                         
9820                         lit >>= 8;
9821                         
9822                 } else if (AOP_TYPE(right) == AOP_CRY) {
9823                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
9824                         if(offset == 0) {
9825                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
9826                                 emitpcode(POC_INCF, popGet(AOP(result),0));
9827                         }
9828                 } else {
9829                         mov2w (AOP(right), offset);
9830                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9831                 }
9832                 
9833                 offset++;
9834         }
9835         
9836         
9837 release:
9838         freeAsmop (right,NULL,ic,FALSE);
9839         freeAsmop (result,NULL,ic,TRUE);
9840 }   
9841
9842 /*-----------------------------------------------------------------*/
9843 /* genJumpTab - genrates code for jump table                       */
9844 /*-----------------------------------------------------------------*/
9845 static void genJumpTab (iCode *ic)
9846 {
9847         symbol *jtab;
9848         char *l;
9849         
9850         FENTRY;
9851         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9852         
9853         aopOp(IC_JTCOND(ic),ic,FALSE);
9854         /* get the condition into accumulator */
9855         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9856         MOVA(l);
9857         /* multiply by three */
9858         pic14_emitcode("add","a,acc");
9859         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9860         
9861         jtab = newiTempLabel(NULL);
9862         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9863         pic14_emitcode("jmp","@a+dptr");
9864         pic14_emitcode("","%05d_DS_:",jtab->key+100);
9865         
9866         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
9867         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
9868         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
9869         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
9870         emitSKPNC;
9871         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
9872         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
9873         emitpLabel(jtab->key);
9874         
9875         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9876         
9877         /* now generate the jump labels */
9878         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9879         jtab = setNextItem(IC_JTLABELS(ic))) {
9880                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
9881                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
9882                 
9883         }
9884         
9885 }
9886
9887 /*-----------------------------------------------------------------*/
9888 /* genMixedOperation - gen code for operators between mixed types  */
9889 /*-----------------------------------------------------------------*/
9890 /*
9891 TSD - Written for the PIC port - but this unfortunately is buggy.
9892 This routine is good in that it is able to efficiently promote 
9893 types to different (larger) sizes. Unfortunately, the temporary
9894 variables that are optimized out by this routine are sometimes
9895 used in other places. So until I know how to really parse the 
9896 iCode tree, I'm going to not be using this routine :(.
9897 */
9898 static int genMixedOperation (iCode *ic)
9899 {
9900         FENTRY;
9901 #if 0
9902         operand *result = IC_RESULT(ic);
9903         sym_link *ctype = operandType(IC_LEFT(ic));
9904         operand *right = IC_RIGHT(ic);
9905         int ret = 0;
9906         int big,small;
9907         int offset;
9908         
9909         iCode *nextic;
9910         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9911         
9912         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9913         
9914         nextic = ic->next;
9915         if(!nextic)
9916                 return 0;
9917         
9918         nextright = IC_RIGHT(nextic);
9919         nextleft  = IC_LEFT(nextic);
9920         nextresult = IC_RESULT(nextic);
9921         
9922         aopOp(right,ic,FALSE);
9923         aopOp(result,ic,FALSE);
9924         aopOp(nextright,  nextic, FALSE);
9925         aopOp(nextleft,   nextic, FALSE);
9926         aopOp(nextresult, nextic, FALSE);
9927         
9928         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9929                 
9930                 operand *t = right;
9931                 right = nextright;
9932                 nextright = t; 
9933                 
9934                 pic14_emitcode(";remove right +","");
9935                 
9936         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9937         /*
9938         operand *t = right;
9939         right = nextleft;
9940         nextleft = t; 
9941                 */
9942                 pic14_emitcode(";remove left +","");
9943         } else
9944                 return 0;
9945         
9946         big = AOP_SIZE(nextleft);
9947         small = AOP_SIZE(nextright);
9948         
9949         switch(nextic->op) {
9950                 
9951         case '+':
9952                 pic14_emitcode(";optimize a +","");
9953                 /* if unsigned or not an integral type */
9954                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9955                         pic14_emitcode(";add a bit to something","");
9956                 } else {
9957                         
9958                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9959                         
9960                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9961                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9962                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9963                         } else
9964                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9965                         
9966                         offset = 0;
9967                         while(--big) {
9968                                 
9969                                 offset++;
9970                                 
9971                                 if(--small) {
9972                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9973                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9974                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9975                                         }
9976                                         
9977                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9978                                         emitSKPNC;
9979                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
9980                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9981                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9982                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9983                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9984                                         
9985                                 } else {
9986                                         pic14_emitcode("rlf","known_zero,w");
9987                                         
9988                                         /*
9989                                         if right is signed
9990                                         btfsc  right,7
9991                                         addlw ff
9992                                         */
9993                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9994                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9995                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9996                                         } else {
9997                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9998                                         }
9999                                 }
10000                         }
10001                         ret = 1;
10002                 }
10003         }
10004         ret = 1;
10005         
10006 release:
10007         freeAsmop(right,NULL,ic,TRUE);
10008         freeAsmop(result,NULL,ic,TRUE);
10009         freeAsmop(nextright,NULL,ic,TRUE);
10010         freeAsmop(nextleft,NULL,ic,TRUE);
10011         if(ret)
10012                 nextic->generated = 1;
10013         
10014         return ret;
10015 #else
10016         return 0;
10017 #endif
10018 }
10019 /*-----------------------------------------------------------------*/
10020 /* genCast - gen code for casting                                  */
10021 /*-----------------------------------------------------------------*/
10022 static void genCast (iCode *ic)
10023 {
10024         operand *result = IC_RESULT(ic);
10025         sym_link *ctype = operandType(IC_LEFT(ic));
10026         sym_link *rtype = operandType(IC_RIGHT(ic));
10027         operand *right = IC_RIGHT(ic);
10028         int size, offset ;
10029         
10030         FENTRY;
10031         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10032         /* if they are equivalent then do nothing */
10033         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10034                 return ;
10035         
10036         aopOp(right,ic,FALSE) ;
10037         aopOp(result,ic,FALSE);
10038         
10039         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10040         
10041         /* if the result is a bit */
10042         if (AOP_TYPE(result) == AOP_CRY) {
10043         /* if the right size is a literal then
10044                 we know what the value is */
10045                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10046                 if (AOP_TYPE(right) == AOP_LIT) {
10047                         
10048                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10049                                 popGet(AOP(result),0));
10050                         
10051                         if (((int) operandLitValue(right))) 
10052                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
10053                                 AOP(result)->aopu.aop_dir,
10054                                 AOP(result)->aopu.aop_dir);
10055                         else
10056                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
10057                                 AOP(result)->aopu.aop_dir,
10058                                 AOP(result)->aopu.aop_dir);
10059                         
10060                         goto release;
10061                 }
10062                 
10063                 /* the right is also a bit variable */
10064                 if (AOP_TYPE(right) == AOP_CRY) {
10065                         
10066                         emitCLRC;
10067                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10068                         
10069                         pic14_emitcode("clrc","");
10070                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10071                                 AOP(right)->aopu.aop_dir,
10072                                 AOP(right)->aopu.aop_dir);
10073                         aopPut(AOP(result),"c",0);
10074                         goto release ;
10075                 }
10076                 
10077                 /* we need to or */
10078                 if (AOP_TYPE(right) == AOP_REG) {
10079                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10080                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
10081                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10082                 }
10083                 pic14_toBoolean(right);
10084                 aopPut(AOP(result),"a",0);
10085                 goto release ;
10086         }
10087         
10088         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10089                 int offset = 1;
10090                 size = AOP_SIZE(result);
10091                 
10092                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10093                 
10094                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10095                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10096                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10097                 
10098                 while (size--)
10099                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10100                 
10101                 goto release;
10102         }
10103         
10104         /* if they are the same size : or less */
10105         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10106                 
10107                 /* if they are in the same place */
10108                 if (pic14_sameRegs(AOP(right),AOP(result)))
10109                         goto release;
10110                 
10111                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10112                 if (IS_PTR_CONST(rtype))
10113                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10114                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10115                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10116                 
10117                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10118                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10119                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10120                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10121                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10122                         if(AOP_SIZE(result) <2)
10123                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10124                         
10125                 } else {
10126                         
10127                         /* if they in different places then copy */
10128                         size = AOP_SIZE(result);
10129                         offset = 0 ;
10130                         while (size--) {
10131                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10132                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10133                                 
10134                                 //aopPut(AOP(result),
10135                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10136                                 // offset);
10137                                 
10138                                 offset++;
10139                         }
10140                 }
10141                 goto release;
10142         }
10143         
10144         
10145         /* if the result is of type pointer */
10146         if (IS_PTR(ctype)) {
10147                 
10148                 int p_type;
10149                 sym_link *type = operandType(right);
10150                 sym_link *etype = getSpec(type);
10151                 DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10152                 
10153                 /* pointer to generic pointer */
10154                 if (IS_GENPTR(ctype)) {
10155                         char *l = zero;
10156                         
10157                         if (IS_PTR(type)) 
10158                                 p_type = DCL_TYPE(type);
10159                         else {
10160                                 /* we have to go by the storage class */
10161                                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10162                                 
10163                                 /*    if (SPEC_OCLS(etype)->codesp )  */
10164                                 /*        p_type = CPOINTER ;  */
10165                                 /*    else */
10166                                 /*        if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10167                                 /*      p_type = FPOINTER ; */
10168                                 /*        else */
10169                                 /*      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10170                                 /*          p_type = PPOINTER; */
10171                                 /*      else */
10172                                 /*          if (SPEC_OCLS(etype) == idata ) */
10173                                 /*        p_type = IPOINTER ; */
10174                                 /*          else */
10175                                 /*        p_type = POINTER ; */
10176                         }
10177                         
10178                         /* the first two bytes are known */
10179                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10180                         size = GPTRSIZE - 1; 
10181                         offset = 0 ;
10182                         while (size--) {
10183                                 if(offset < AOP_SIZE(right)) {
10184                                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10185                                         if ((AOP_TYPE(right) == AOP_PCODE) && 
10186                                                 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10187                                                 emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
10188                                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10189                                         } else { 
10190                                                 aopPut(AOP(result),
10191                                                         aopGet(AOP(right),offset,FALSE,FALSE),
10192                                                         offset);
10193                                         }
10194                                 } else 
10195                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
10196                                 offset++;
10197                         }
10198                         /* the last byte depending on type */
10199                         switch (p_type) {
10200                         case IPOINTER:
10201                         case POINTER:
10202                                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
10203                                 break;
10204                         case FPOINTER:
10205                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10206                                 l = one;
10207                                 break;
10208                         case CPOINTER:
10209                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10210                                 l = "#0x02";
10211                                 break;        
10212                         case PPOINTER:
10213                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10214                                 l = "#0x03";
10215                                 break;
10216                                 
10217                         default:
10218                                 /* this should never happen */
10219                                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10220                                         "got unknown pointer type");
10221                                 exit(1);
10222                         }
10223                         //aopPut(AOP(result),l, GPTRSIZE - 1);      
10224                         goto release ;
10225                 }
10226                 
10227                 /* just copy the pointers */
10228                 size = AOP_SIZE(result);
10229                 offset = 0 ;
10230                 while (size--) {
10231                         aopPut(AOP(result),
10232                                 aopGet(AOP(right),offset,FALSE,FALSE),
10233                                 offset);
10234                         offset++;
10235                 }
10236                 goto release ;
10237         }
10238         
10239         
10240         
10241         /* so we now know that the size of destination is greater
10242         than the size of the source.
10243         Now, if the next iCode is an operator then we might be
10244         able to optimize the operation without performing a cast.
10245         */
10246         if(genMixedOperation(ic))
10247                 goto release;
10248         
10249         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10250         
10251         /* we move to result for the size of source */
10252         size = AOP_SIZE(right);
10253         offset = 0 ;
10254         while (size--) {
10255                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10256                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10257                 offset++;
10258         }
10259         
10260         /* now depending on the sign of the destination */
10261         size = AOP_SIZE(result) - AOP_SIZE(right);
10262         /* if unsigned or not an integral type */
10263         if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10264                 while (size--)
10265                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10266         } else {
10267                 /* we need to extend the sign :{ */
10268                 
10269                 if(size == 1) {
10270                         /* Save one instruction of casting char to int */
10271                         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
10272                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10273                         emitpcode(POC_DECF,   popGet(AOP(result),offset));
10274                 } else {
10275                         emitpcodeNULLop(POC_CLRW);
10276                         
10277                         if(offset)
10278                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10279                         else
10280                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10281                         
10282                         emitpcode(POC_MOVLW,   popGetLit(0xff));
10283                         
10284                         while (size--)
10285                                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
10286                 }
10287         }
10288         
10289 release:
10290         freeAsmop(right,NULL,ic,TRUE);
10291         freeAsmop(result,NULL,ic,TRUE);
10292         
10293 }
10294
10295 /*-----------------------------------------------------------------*/
10296 /* genDjnz - generate decrement & jump if not zero instrucion      */
10297 /*-----------------------------------------------------------------*/
10298 static int genDjnz (iCode *ic, iCode *ifx)
10299 {
10300         symbol *lbl, *lbl1;
10301         FENTRY;
10302         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10303         
10304         if (!ifx)
10305                 return 0;
10306         
10307                 /* if the if condition has a false label
10308         then we cannot save */
10309         if (IC_FALSE(ifx))
10310                 return 0;
10311         
10312                 /* if the minus is not of the form 
10313         a = a - 1 */
10314         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10315                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10316                 return 0;
10317         
10318         if (operandLitValue(IC_RIGHT(ic)) != 1)
10319                 return 0;
10320         
10321                 /* if the size of this greater than one then no
10322         saving */
10323         if (getSize(operandType(IC_RESULT(ic))) > 1)
10324                 return 0;
10325         
10326         /* otherwise we can save BIG */
10327         lbl = newiTempLabel(NULL);
10328         lbl1= newiTempLabel(NULL);
10329         
10330         aopOp(IC_RESULT(ic),ic,FALSE);
10331         
10332         if (IS_AOP_PREG(IC_RESULT(ic))) {
10333                 pic14_emitcode("dec","%s",
10334                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10335                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10336                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10337         } else {  
10338                 
10339                 
10340                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10341                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10342                 
10343                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10344                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10345                 
10346         }
10347         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10348         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10349         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10350         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10351         
10352         
10353         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10354         ifx->generated = 1;
10355         return 1;
10356 }
10357
10358 /*-----------------------------------------------------------------*/
10359 /* genReceive - generate code for a receive iCode                  */
10360 /*-----------------------------------------------------------------*/
10361 static void genReceive (iCode *ic)
10362 {
10363         FENTRY;
10364         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10365         
10366         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10367                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10368                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10369                 
10370                 int size = getSize(operandType(IC_RESULT(ic)));
10371                 int offset =  fReturnSizePic - size;
10372                 while (size--) {
10373                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10374                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10375                         offset++;
10376                 }
10377                 aopOp(IC_RESULT(ic),ic,FALSE);
10378                 size = AOP_SIZE(IC_RESULT(ic));
10379                 offset = 0;
10380                 while (size--) {
10381                         pic14_emitcode ("pop","acc");
10382                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10383                 }
10384                 
10385         } else {
10386                 _G.accInUse++;
10387                 aopOp(IC_RESULT(ic),ic,FALSE);
10388                 _G.accInUse--;
10389                 assignResultValue(IC_RESULT(ic));
10390         }
10391         
10392         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10393 }
10394
10395 /*-----------------------------------------------------------------*/
10396 /* genDummyRead - generate code for dummy read of volatiles        */
10397 /*-----------------------------------------------------------------*/
10398 static void
10399 genDummyRead (iCode * ic)
10400 {
10401         FENTRY;
10402         pic14_emitcode ("; genDummyRead","");
10403         pic14_emitcode ("; not implemented","");
10404         
10405         ic = ic;
10406 }
10407
10408 /*-----------------------------------------------------------------*/
10409 /* genpic14Code - generate code for pic14 based controllers        */
10410 /*-----------------------------------------------------------------*/
10411 /*
10412 * At this point, ralloc.c has gone through the iCode and attempted
10413 * to optimize in a way suitable for a PIC. Now we've got to generate
10414 * PIC instructions that correspond to the iCode.
10415 *
10416 * Once the instructions are generated, we'll pass through both the
10417 * peep hole optimizer and the pCode optimizer.
10418 *-----------------------------------------------------------------*/
10419
10420 void genpic14Code (iCode *lic)
10421 {
10422         iCode *ic;
10423         int cln = 0;
10424         const char *cline;
10425         
10426         FENTRY;
10427         lineHead = lineCurr = NULL;
10428         
10429         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10430         addpBlock(pb);
10431         
10432         /* if debug information required */
10433         if (options.debug && currFunc) { 
10434                 if (currFunc) {
10435                         debugFile->writeFunction (currFunc, lic);
10436                 }
10437         }
10438         
10439         
10440         for (ic = lic ; ic ; ic = ic->next ) {
10441                 
10442                 //DEBUGpic14_emitcode(";ic","");
10443                 //fprintf (stderr, "in ic loop\n");
10444                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10445                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10446                 
10447                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10448                   cln = ic->lineno;
10449                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10450                   cline = printCLine (ic->filename, ic->lineno);
10451                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10452                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10453                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10454                 }
10455                 
10456                 if (options.iCodeInAsm) {
10457                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10458                 }
10459                 /* if the result is marked as
10460                 spilt and rematerializable or code for
10461                 this has already been generated then
10462                 do nothing */
10463                 if (resultRemat(ic) || ic->generated ) 
10464                         continue ;
10465                 
10466                 /* depending on the operation */
10467                 switch (ic->op) {
10468                 case '!' :
10469                         genNot(ic);
10470                         break;
10471                         
10472                 case '~' :
10473                         genCpl(ic);
10474                         break;
10475                         
10476                 case UNARYMINUS:
10477                         genUminus (ic);
10478                         break;
10479                         
10480                 case IPUSH:
10481                         genIpush (ic);
10482                         break;
10483                         
10484                 case IPOP:
10485                         /* IPOP happens only when trying to restore a 
10486                         spilt live range, if there is an ifx statement
10487                         following this pop then the if statement might
10488                         be using some of the registers being popped which
10489                         would destory the contents of the register so
10490                         we need to check for this condition and handle it */
10491                         if (ic->next            && 
10492                                 ic->next->op == IFX &&
10493                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10494                                 genIfx (ic->next,ic);
10495                         else
10496                                 genIpop (ic);
10497                         break; 
10498                         
10499                 case CALL:
10500                         genCall (ic);
10501                         break;
10502                         
10503                 case PCALL:
10504                         genPcall (ic);
10505                         break;
10506                         
10507                 case FUNCTION:
10508                         genFunction (ic);
10509                         break;
10510                         
10511                 case ENDFUNCTION:
10512                         genEndFunction (ic);
10513                         break;
10514                         
10515                 case RETURN:
10516                         genRet (ic);
10517                         break;
10518                         
10519                 case LABEL:
10520                         genLabel (ic);
10521                         break;
10522                         
10523                 case GOTO:
10524                         genGoto (ic);
10525                         break;
10526                         
10527                 case '+' :
10528                         genPlus (ic) ;
10529                         break;
10530                         
10531                 case '-' :
10532                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10533                                 genMinus (ic);
10534                         break;
10535                         
10536                 case '*' :
10537                         genMult (ic);
10538                         break;
10539                         
10540                 case '/' :
10541                         genDiv (ic) ;
10542                         break;
10543                         
10544                 case '%' :
10545                         genMod (ic);
10546                         break;
10547                         
10548                 case '>' :
10549                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10550                         break;
10551                         
10552                 case '<' :
10553                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10554                         break;
10555                         
10556                 case LE_OP:
10557                 case GE_OP:
10558                 case NE_OP:
10559                         
10560                         /* note these two are xlated by algebraic equivalence
10561                         during parsing SDCC.y */
10562                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10563                                 "got '>=' or '<=' shouldn't have come here");
10564                         break;  
10565                         
10566                 case EQ_OP:
10567                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10568                         break;      
10569                         
10570                 case AND_OP:
10571                         genAndOp (ic);
10572                         break;
10573                         
10574                 case OR_OP:
10575                         genOrOp (ic);
10576                         break;
10577                         
10578                 case '^' :
10579                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10580                         break;
10581                         
10582                 case '|' :
10583                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10584                         break;
10585                         
10586                 case BITWISEAND:
10587                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10588                         break;
10589                         
10590                 case INLINEASM:
10591                         genInline (ic);
10592                         break;
10593                         
10594                 case RRC:
10595                         genRRC (ic);
10596                         break;
10597                         
10598                 case RLC:
10599                         genRLC (ic);
10600                         break;
10601                         
10602                 case GETHBIT:
10603                         genGetHbit (ic);
10604                         break;
10605                         
10606                 case LEFT_OP:
10607                         genLeftShift (ic);
10608                         break;
10609                         
10610                 case RIGHT_OP:
10611                         genRightShift (ic);
10612                         break;
10613                         
10614                 case GET_VALUE_AT_ADDRESS:
10615                         genPointerGet(ic);
10616                         break;
10617                         
10618                 case '=' :
10619                         if (POINTER_SET(ic))
10620                                 genPointerSet(ic);
10621                         else
10622                                 genAssign(ic);
10623                         break;
10624                         
10625                 case IFX:
10626                         genIfx (ic,NULL);
10627                         break;
10628                         
10629                 case ADDRESS_OF:
10630                         genAddrOf (ic);
10631                         break;
10632                         
10633                 case JUMPTABLE:
10634                         genJumpTab (ic);
10635                         break;
10636                         
10637                 case CAST:
10638                         genCast (ic);
10639                         break;
10640                         
10641                 case RECEIVE:
10642                         genReceive(ic);
10643                         break;
10644                         
10645                 case SEND:
10646                         addSet(&_G.sendSet,ic);
10647                         break;
10648                         
10649                 case DUMMY_READ_VOLATILE:
10650                         genDummyRead (ic);
10651                         break;
10652                         
10653                 default :
10654                         ic = ic;
10655                 }
10656         }
10657
10658         
10659         /* now we are ready to call the
10660         peep hole optimizer */
10661         if (!options.nopeep) {
10662                 peepHole (&lineHead);
10663         }
10664         /* now do the actual printing */
10665         printLine (lineHead,codeOutFile);
10666         
10667 #ifdef PCODE_DEBUG
10668         DFPRINTF((stderr,"printing pBlock\n\n"));
10669         printpBlock(stdout,pb);
10670 #endif
10671         
10672         return;
10673 }
10674
10675 int
10676 aop_isLitLike (asmop *aop)
10677 {
10678   assert (aop);
10679   if (aop->type == AOP_LIT) return 1;
10680   if (aop->type == AOP_IMMD) return 1;
10681   if ((aop->type == AOP_PCODE) &&
10682                 ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
10683   {
10684     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10685      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10686     return 1;
10687   }
10688   return 0;
10689 }
10690
10691 int
10692 op_isLitLike (operand *op)
10693 {
10694   assert (op);
10695   if (aop_isLitLike (AOP(op))) return 1;
10696   return 0;
10697 }