* src/SDCCmain.c (linkEdit): initialized linkerScriptFileName,
[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 = NULL; /* this is wrong: 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)
904                 {
905                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
906                         {
907                                 /* force a new aop if sizes differ */
908                                 sym->usl.spillLoc->aop = NULL;
909                         }
910                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
911                                 __FUNCTION__,__LINE__,
912                                 sym->usl.spillLoc->rname,
913                                 sym->rname, sym->usl.spillLoc->offset);
914                 
915                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
916                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
917                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
918                                 getSize(sym->type), 
919                                 sym->usl.spillLoc->offset);
920                         aop->size = getSize(sym->type);
921                 
922                         return;
923                 }
924         }
925         
926         {
927                 sym_link *type = operandType(op);
928                 if(IS_PTR_CONST(type)) 
929                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
930         }
931         
932         /* must be in a register */
933         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
934         sym->aop = op->aop = aop = newAsmop(AOP_REG);
935         aop->size = sym->nRegs;
936         for ( i = 0 ; i < sym->nRegs ;i++)
937                 aop->aopu.aop_reg[i] = sym->regs[i];
938 }
939
940 /*-----------------------------------------------------------------*/
941 /* freeAsmop - free up the asmop given to an operand                       */
942 /*----------------------------------------------------------------*/
943 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
944 {       
945         asmop *aop ;
946         
947         if (!op)
948                 aop = aaop;
949         else 
950                 aop = op->aop;
951         
952         if (!aop)
953                 return ;
954         
955         if (aop->freed)
956                 goto dealloc; 
957         
958         aop->freed = 1;
959         
960         /* depending on the asmop type only three cases need work AOP_RO
961         , AOP_R1 && AOP_STK */
962 #if 0
963         switch (aop->type) {
964         case AOP_R0 :
965                 if (_G.r0Pushed ) {
966                         if (pop) {
967                                 pic14_emitcode ("pop","ar0");     
968                                 _G.r0Pushed--;
969                         }
970                 }
971                 bitVectUnSetBit(ic->rUsed,R0_IDX);
972                 break;
973                 
974         case AOP_R1 :
975                 if (_G.r1Pushed ) {
976                         if (pop) {
977                                 pic14_emitcode ("pop","ar1");
978                                 _G.r1Pushed--;
979                         }
980                 }
981                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
982                 break;
983                 
984         case AOP_STK :
985                 {
986                         int sz = aop->size;      
987                         int stk = aop->aopu.aop_stk + aop->size;
988                         bitVectUnSetBit(ic->rUsed,R0_IDX);
989                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
990                         
991                         getFreePtr(ic,&aop,FALSE);
992                         
993                         if (options.stack10bit)
994                         {
995                                 /* I'm not sure what to do here yet... */
996                                 /* #STUB */
997                                 fprintf(stderr, 
998                                         "*** Warning: probably generating bad code for "
999                                         "10 bit stack mode.\n");
1000                         }
1001                         
1002                         if (stk) {
1003                                 pic14_emitcode ("mov","a,_bp");
1004                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1005                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1006                         } else {
1007                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1008                         }
1009                         
1010                         while (sz--) {
1011                                 pic14_emitcode("pop","acc");
1012                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1013                                 if (!sz) break;
1014                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1015                         }
1016                         op->aop = aop;
1017                         freeAsmop(op,NULL,ic,TRUE);
1018                         if (_G.r0Pushed) {
1019                                 pic14_emitcode("pop","ar0");
1020                                 _G.r0Pushed--;
1021                         }
1022                         
1023                         if (_G.r1Pushed) {
1024                                 pic14_emitcode("pop","ar1");
1025                                 _G.r1Pushed--;
1026                         }         
1027                 }
1028         }
1029 #endif
1030         
1031 dealloc:
1032         /* all other cases just dealloc */
1033         if (op ) {
1034                 op->aop = NULL;
1035                 if (IS_SYMOP(op)) {
1036                         OP_SYMBOL(op)->aop = NULL;      
1037                         /* if the symbol has a spill */
1038                         if (SPIL_LOC(op))
1039                                 SPIL_LOC(op)->aop = NULL;
1040                 }
1041         }
1042 }
1043
1044 /*-----------------------------------------------------------------*/
1045 /* aopGet - for fetching value of the aop                                                  */
1046 /*-----------------------------------------------------------------*/
1047 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1048 {
1049         char *s = buffer ;
1050         char *rs;
1051         
1052         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1053         /* offset is greater than
1054         size then zero */
1055         if (offset > (aop->size - 1) &&
1056                 aop->type != AOP_LIT)
1057                 return zero;
1058         
1059         /* depending on type */
1060         switch (aop->type) {
1061                 
1062         case AOP_R0:
1063         case AOP_R1:
1064                 DEBUGpic14_emitcode(";","%d",__LINE__);
1065                 /* if we need to increment it */           
1066                 while (offset > aop->coff) {            
1067                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1068                         aop->coff++;
1069                 }
1070                 
1071                 while (offset < aop->coff) {
1072                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1073                         aop->coff--;
1074                 }
1075                 
1076                 aop->coff = offset ;
1077                 if (aop->paged) {
1078                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1079                         return (dname ? "acc" : "a");
1080                 }               
1081                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1082                 rs = Safe_calloc(1,strlen(s)+1);
1083                 strcpy(rs,s);   
1084                 return rs;
1085                 
1086         case AOP_DPTR:
1087         case AOP_DPTR2:
1088                 DEBUGpic14_emitcode(";","%d",__LINE__);
1089                 if (aop->type == AOP_DPTR2)
1090                 {
1091                         genSetDPTR(1);
1092                 }
1093                 
1094                 while (offset > aop->coff) {
1095                         pic14_emitcode ("inc","dptr");
1096                         aop->coff++;
1097                 }
1098                 
1099                 while (offset < aop->coff) {            
1100                         pic14_emitcode("lcall","__decdptr");
1101                         aop->coff--;
1102                 }
1103                 
1104                 aop->coff = offset;
1105                 if (aop->code) {
1106                         pic14_emitcode("clr","a");
1107                         pic14_emitcode("movc","a,@a+dptr");
1108                 }
1109                 else {
1110                         pic14_emitcode("movx","a,@dptr");
1111                 }
1112                 
1113                 if (aop->type == AOP_DPTR2)
1114                 {
1115                         genSetDPTR(0);
1116                 }
1117                 
1118                 return (dname ? "acc" : "a");
1119                 
1120                 
1121         case AOP_IMMD:
1122                 if (bit16) 
1123                         sprintf (s,"%s",aop->aopu.aop_immd);
1124                 else
1125                         if (offset) 
1126                                 sprintf(s,"(%s >> %d)",
1127                                 aop->aopu.aop_immd,
1128                                 offset*8);
1129                         else
1130                                 sprintf(s,"%s",
1131                                 aop->aopu.aop_immd);
1132                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1133                         rs = Safe_calloc(1,strlen(s)+1);
1134                         strcpy(rs,s);   
1135                         return rs;
1136                         
1137         case AOP_DIR:
1138                 if (offset) {
1139                         sprintf(s,"(%s + %d)",
1140                                 aop->aopu.aop_dir,
1141                                 offset);
1142                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1143                 } else
1144                         sprintf(s,"%s",aop->aopu.aop_dir);
1145                 rs = Safe_calloc(1,strlen(s)+1);
1146                 strcpy(rs,s);   
1147                 return rs;
1148                 
1149         case AOP_REG:
1150                 //if (dname) 
1151                 //        return aop->aopu.aop_reg[offset]->dname;
1152                 //else
1153                 return aop->aopu.aop_reg[offset]->name;
1154                 
1155         case AOP_CRY:
1156                 //pic14_emitcode(";","%d",__LINE__);
1157                 return aop->aopu.aop_dir;
1158                 
1159         case AOP_ACC:
1160                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1161                 return "AOP_accumulator_bug";
1162                 
1163         case AOP_LIT:
1164                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1165                 rs = Safe_calloc(1,strlen(s)+1);
1166                 strcpy(rs,s);   
1167                 return rs;
1168                 
1169         case AOP_STR:
1170                 aop->coff = offset ;
1171                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1172                         dname)
1173                         return "acc";
1174                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1175                 
1176                 return aop->aopu.aop_str[offset];
1177                 
1178         case AOP_PCODE:
1179                 {
1180                         pCodeOp *pcop = aop->aopu.pcop;
1181                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1182                         if(pcop->name) {
1183                                 if (offset) {
1184                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1185                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1186                                 } else {
1187                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1188                                         sprintf(s,"%s", pcop->name);
1189                                 }
1190                         } else
1191                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1192                         
1193                 }
1194                 rs = Safe_calloc(1,strlen(s)+1);
1195                 strcpy(rs,s);   
1196                 return rs;
1197                 
1198   }
1199   
1200   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1201           "aopget got unsupported aop->type");
1202   exit(0);
1203 }
1204
1205
1206 /*-----------------------------------------------------------------*/
1207 /* popGetTempReg - create a new temporary pCodeOp                                  */
1208 /*-----------------------------------------------------------------*/
1209 pCodeOp *popGetTempReg(void)
1210 {
1211         
1212         pCodeOp *pcop;
1213         
1214         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1215         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1216                 PCOR(pcop)->r->wasUsed=1;
1217                 PCOR(pcop)->r->isFree=0;
1218         }
1219         
1220         return pcop;
1221 }
1222
1223 /*-----------------------------------------------------------------*/
1224 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1225 /*-----------------------------------------------------------------*/
1226 void popReleaseTempReg(pCodeOp *pcop)
1227 {
1228         
1229         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1230                 PCOR(pcop)->r->isFree = 1;
1231         
1232 }
1233 /*-----------------------------------------------------------------*/
1234 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1235 /*-----------------------------------------------------------------*/
1236 pCodeOp *popGetLabel(unsigned int key)
1237 {
1238         
1239         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1240         
1241         if(key>(unsigned int)max_key)
1242                 max_key = key;
1243         
1244         return newpCodeOpLabel(NULL,key+100+labelOffset);
1245 }
1246
1247 /*-------------------------------------------------------------------*/
1248 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1249 /*-------------------------------------------------------------------*/
1250 pCodeOp *popGetHighLabel(unsigned int key)
1251 {
1252         pCodeOp *pcop;
1253         pcop = popGetLabel(key);
1254         PCOLAB(pcop)->offset = 1;
1255         return pcop;
1256 }
1257
1258 /*-----------------------------------------------------------------*/
1259 /* popGetLit - asm operator to pcode operator conversion                           */
1260 /*-----------------------------------------------------------------*/
1261 pCodeOp *popGetLit(unsigned int lit)
1262 {
1263         
1264         return newpCodeOpLit(lit);
1265 }
1266
1267 /*-----------------------------------------------------------------*/
1268 /* popGetImmd - asm operator to pcode immediate conversion                 */
1269 /*-----------------------------------------------------------------*/
1270 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1271 {
1272         
1273         return newpCodeOpImmd(name, offset,index, 0, is_func);
1274 }
1275
1276
1277 /*-----------------------------------------------------------------*/
1278 /* popGetWithString - asm operator to pcode operator conversion                    */
1279 /*-----------------------------------------------------------------*/
1280 pCodeOp *popGetWithString(char *str, int isExtern)
1281 {
1282         pCodeOp *pcop;
1283         
1284         
1285         if(!str) {
1286                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1287                 exit (1);
1288         }
1289         
1290         pcop = newpCodeOp(str,PO_STR);
1291         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1292         
1293         return pcop;
1294 }
1295
1296 /*-----------------------------------------------------------------*/
1297 /* popRegFromString -                                                                                      */
1298 /*-----------------------------------------------------------------*/
1299 pCodeOp *popRegFromString(char *str, int size, int offset)
1300 {
1301         
1302         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1303         pcop->type = PO_DIR;
1304         
1305         DEBUGpic14_emitcode(";","%d",__LINE__);
1306         
1307         if(!str)
1308                 str = "BAD_STRING";
1309         
1310         pcop->name = Safe_calloc(1,strlen(str)+1);
1311         strcpy(pcop->name,str);
1312         
1313         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1314         
1315         PCOR(pcop)->r = dirregWithName(pcop->name);
1316         if(PCOR(pcop)->r == NULL) {
1317                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1318                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1319                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1320         } else {
1321                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1322         }
1323         PCOR(pcop)->instance = offset;
1324         
1325         return pcop;
1326 }
1327
1328 /*-----------------------------------------------------------------*/
1329 /*-----------------------------------------------------------------*/
1330 pCodeOp *popRegFromIdx(int rIdx)
1331 {
1332         pCodeOp *pcop;
1333         
1334         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1335                 __FUNCTION__,__LINE__,rIdx);
1336         
1337         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1338         
1339         PCOR(pcop)->rIdx = rIdx;
1340         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1341         PCOR(pcop)->r->isFree = 0;
1342         PCOR(pcop)->r->wasUsed = 1;
1343         
1344         pcop->type = PCOR(pcop)->r->pc_type;
1345         
1346         
1347         return pcop;
1348 }
1349
1350 /*-----------------------------------------------------------------*/
1351 /* popGet - asm operator to pcode operator conversion                      */
1352 /*-----------------------------------------------------------------*/
1353 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1354 {
1355         //char *s = buffer ;
1356         //char *rs;
1357         
1358         pCodeOp *pcop;
1359         
1360         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1361         /* offset is greater than
1362         size then zero */
1363
1364         if (!(offset >= 0 && ((offset < aop->size) || (aop->size == 0))))
1365         {
1366           fprintf (stderr, "%s:%u: offset=%d, aop-type:%s, size:%d\n", __FILE__, __LINE__, offset, AopType (aop->type), aop->size);
1367         }
1368         assert (offset >= 0 && ((offset < aop->size) || (aop->size == 0)));
1369         
1370         /* XXX: still needed for BIT operands (AOP_CRY) */
1371         if (offset > (aop->size - 1) &&
1372                 aop->type != AOP_LIT)
1373                 return NULL;  //zero;
1374         
1375         /* depending on type */
1376         switch (aop->type) {
1377                 
1378         case AOP_R0:
1379         case AOP_R1:
1380         case AOP_DPTR:
1381         case AOP_DPTR2:
1382         case AOP_ACC:
1383                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1384                 return NULL;
1385                 
1386         case AOP_IMMD:
1387                 DEBUGpic14_emitcode(";","%d",__LINE__);
1388                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1389                 
1390         case AOP_DIR:
1391                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1392 #if 0
1393                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1394                 pcop->type = PO_DIR;
1395                 
1396                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1397                 strcpy(pcop->name,aop->aopu.aop_dir);   
1398                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1399                 if(PCOR(pcop)->r == NULL) {
1400                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1401                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1402                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1403                 } else {
1404                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1405                 }
1406                 PCOR(pcop)->instance = offset;
1407                 
1408                 return pcop;
1409 #endif
1410                 
1411         case AOP_REG:
1412                 {
1413                         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1414                         
1415                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1416                         PCOR(pcop)->rIdx = rIdx;
1417                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1418                         PCOR(pcop)->r->wasUsed=1;
1419                         PCOR(pcop)->r->isFree=0;
1420                         
1421                         PCOR(pcop)->instance = offset;
1422                         pcop->type = PCOR(pcop)->r->pc_type;
1423                         //rs = aop->aopu.aop_reg[offset]->name;
1424                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1425                         return pcop;
1426                 }
1427                 
1428         case AOP_CRY:
1429                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1430                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1431                 //if(PCOR(pcop)->r == NULL)
1432                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1433                 return pcop;
1434                 
1435         case AOP_LIT:
1436                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1437                 
1438         case AOP_STR:
1439                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1440                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1441                 /*
1442                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1443                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1444                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1445                 pcop->type = PCOR(pcop)->r->pc_type;
1446                 pcop->name = PCOR(pcop)->r->name;
1447                 
1448                   return pcop;
1449                 */
1450                 
1451         case AOP_PCODE:
1452                 pcop = NULL;
1453                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1454                         __LINE__, 
1455                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1456                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1457                 switch (aop->aopu.pcop->type)
1458                 {
1459                 case PO_IMMEDIATE:
1460                   pcop = pCodeOpCopy (aop->aopu.pcop);
1461                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1462                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1463                   PCOI(pcop)->index += offset;
1464                   //PCOI(pcop)->offset = 0;
1465                   break;
1466                 case PO_DIR:
1467                   pcop = pCodeOpCopy (aop->aopu.pcop);
1468                   PCOR(pcop)->instance = offset;
1469                   break;
1470                 default:
1471                   assert ( !"unhandled pCode type" );
1472                   break;
1473                 } // switch
1474                 return pcop;
1475         }
1476         
1477         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1478                 "popGet got unsupported aop->type");
1479         exit(0);
1480 }
1481
1482 /*-----------------------------------------------------------------*/
1483 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1484 /*              (for non-PO_IMMEDIATEs this is the same as poGet)  */
1485 /*-----------------------------------------------------------------*/
1486 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1487 {
1488   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1489   {
1490     pCodeOp *pcop = aop->aopu.pcop;
1491     pcop = pCodeOpCopy (pcop);
1492     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1493      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1494     PCOI(pcop)->offset += offset;
1495     PCOI(pcop)->index += index;
1496     return pcop;
1497   } else {
1498     return popGet (aop, offset + index);
1499   }
1500 }
1501
1502 /*-----------------------------------------------------------------*/
1503 /* aopPut - puts a string for a aop                                                        */
1504 /*-----------------------------------------------------------------*/
1505 void aopPut (asmop *aop, char *s, int offset)
1506 {
1507         char *d = buffer ;
1508         symbol *lbl ;
1509         
1510         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1511         
1512         if (aop->size && offset > ( aop->size - 1)) {
1513                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1514                         "aopPut got offset > aop->size");
1515                 exit(0);
1516         }
1517         
1518         /* will assign value to value */
1519         /* depending on where it is ofcourse */
1520         switch (aop->type) {
1521         case AOP_DIR:
1522                 if (offset) {
1523                         sprintf(d,"(%s + %d)",
1524                                 aop->aopu.aop_dir,offset);
1525                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1526                         
1527                 } else
1528                         sprintf(d,"%s",aop->aopu.aop_dir);
1529                 
1530                 if (strcmp(d,s)) {
1531                         DEBUGpic14_emitcode(";","%d",__LINE__);
1532                         if(strcmp(s,"W"))
1533                                 pic14_emitcode("movf","%s,w",s);
1534                         pic14_emitcode("movwf","%s",d);
1535                         
1536                         if(strcmp(s,"W")) {
1537                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1538                                 if(offset >= aop->size) {
1539                                         emitpcode(POC_CLRF,popGet(aop,offset));
1540                                         break;
1541                                 } else
1542                                         emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1543                         }
1544                         
1545                         emitpcode(POC_MOVWF,popGet(aop,offset));
1546                         
1547                         
1548                 }
1549                 break;
1550                 
1551         case AOP_REG:
1552                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1553                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1554                         /*
1555                         if (*s == '@'             ||
1556                         strcmp(s,"r0") == 0 ||
1557                         strcmp(s,"r1") == 0 ||
1558                         strcmp(s,"r2") == 0 ||
1559                         strcmp(s,"r3") == 0 ||
1560                         strcmp(s,"r4") == 0 ||
1561                         strcmp(s,"r5") == 0 ||
1562                         strcmp(s,"r6") == 0 || 
1563                         strcmp(s,"r7") == 0 )
1564                         pic14_emitcode("mov","%s,%s  ; %d",
1565                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1566                         else
1567                         */
1568                         
1569                         if(strcmp(s,"W")==0 )
1570                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1571                         
1572                         pic14_emitcode("movwf","%s",
1573                                 aop->aopu.aop_reg[offset]->name);
1574                         
1575                         if(strcmp(s,zero)==0) {
1576                                 emitpcode(POC_CLRF,popGet(aop,offset));
1577                                 
1578                         } else if(strcmp(s,"W")==0) {
1579                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1580                                 pcop->type = PO_GPR_REGISTER;
1581                                 
1582                                 PCOR(pcop)->rIdx = -1;
1583                                 PCOR(pcop)->r = NULL;
1584                                 
1585                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1586                                 pcop->name = Safe_strdup(s);
1587                                 emitpcode(POC_MOVFW,pcop);
1588                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1589                         } else if(strcmp(s,one)==0) {
1590                                 emitpcode(POC_CLRF,popGet(aop,offset));
1591                                 emitpcode(POC_INCF,popGet(aop,offset));
1592                         } else {
1593                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1594                         }
1595                 }
1596                 break;
1597                 
1598         case AOP_DPTR:
1599         case AOP_DPTR2:
1600                 
1601                 if (aop->type == AOP_DPTR2)
1602                 {
1603                         genSetDPTR(1);
1604                 }
1605                 
1606                 if (aop->code) {
1607                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1608                                 "aopPut writting to code space");
1609                         exit(0);
1610                 }
1611                 
1612                 while (offset > aop->coff) {
1613                         aop->coff++;
1614                         pic14_emitcode ("inc","dptr");
1615                 }
1616                 
1617                 while (offset < aop->coff) {
1618                         aop->coff-- ;
1619                         pic14_emitcode("lcall","__decdptr");
1620                 }
1621                 
1622                 aop->coff = offset;
1623                 
1624                 /* if not in accumulater */
1625                 MOVA(s);
1626                 
1627                 pic14_emitcode ("movx","@dptr,a");
1628                 
1629                 if (aop->type == AOP_DPTR2)
1630                 {
1631                         genSetDPTR(0);
1632                 }
1633                 break;
1634                 
1635         case AOP_R0:
1636         case AOP_R1:
1637                 while (offset > aop->coff) {
1638                         aop->coff++;
1639                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1640                 }
1641                 while (offset < aop->coff) {
1642                         aop->coff-- ;
1643                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1644                 }
1645                 aop->coff = offset;
1646                 
1647                 if (aop->paged) {
1648                         MOVA(s);                         
1649                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1650                         
1651                 } else
1652                         if (*s == '@') {
1653                                 MOVA(s);
1654                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1655                         } else
1656                                 if (strcmp(s,"r0") == 0 ||
1657                                         strcmp(s,"r1") == 0 ||
1658                                         strcmp(s,"r2") == 0 ||
1659                                         strcmp(s,"r3") == 0 ||
1660                                         strcmp(s,"r4") == 0 ||
1661                                         strcmp(s,"r5") == 0 ||
1662                                         strcmp(s,"r6") == 0 || 
1663                                         strcmp(s,"r7") == 0 ) {
1664                                         char buffer[10];
1665                                         sprintf(buffer,"a%s",s);
1666                                         pic14_emitcode("mov","@%s,%s",
1667                                                 aop->aopu.aop_ptr->name,buffer);
1668                                 } else
1669                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1670                                 
1671                                 break;
1672                                 
1673         case AOP_STK:
1674                 if (strcmp(s,"a") == 0)
1675                         pic14_emitcode("push","acc");
1676                 else
1677                         pic14_emitcode("push","%s",s);
1678                 
1679                 break;
1680                 
1681         case AOP_CRY:
1682                 /* if bit variable */
1683                 if (!aop->aopu.aop_dir) {
1684                         pic14_emitcode("clr","a");
1685                         pic14_emitcode("rlc","a");
1686                 } else {
1687                         if (s == zero) 
1688                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1689                         else
1690                                 if (s == one)
1691                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1692                                 else
1693                                         if (!strcmp(s,"c"))
1694                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1695                                         else {
1696                                                 lbl = newiTempLabel(NULL);
1697                                                 
1698                                                 if (strcmp(s,"a")) {
1699                                                         MOVA(s);
1700                                                 }
1701                                                 pic14_emitcode("clr","c");
1702                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1703                                                 pic14_emitcode("cpl","c");
1704                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1705                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1706                                         }
1707                 }
1708                 break;
1709                 
1710         case AOP_STR:
1711                 aop->coff = offset;
1712                 if (strcmp(aop->aopu.aop_str[offset],s))
1713                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1714                 break;
1715                 
1716         case AOP_ACC:
1717                 aop->coff = offset;
1718                 if (!offset && (strcmp(s,"acc") == 0))
1719                         break;
1720                 
1721                 if (strcmp(aop->aopu.aop_str[offset],s))
1722                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1723                 break;
1724                 
1725         default :
1726                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1727                         "aopPut got unsupported aop->type");
1728                 exit(0);
1729         }
1730         
1731 }
1732
1733 /*-----------------------------------------------------------------*/
1734 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1735 /*-----------------------------------------------------------------*/
1736 void mov2w (asmop *aop, int offset)
1737 {
1738         
1739         if(!aop)
1740                 return;
1741         
1742         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1743         
1744         if ( aop_isLitLike (aop) )
1745                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1746         else
1747                 emitpcode(POC_MOVFW,popGet(aop,offset));
1748         
1749 }
1750
1751 /*-----------------------------------------------------------------*/
1752 /* reAdjustPreg - points a register back to where it should        */
1753 /*-----------------------------------------------------------------*/
1754 static void reAdjustPreg (asmop *aop)
1755 {
1756         int size ;
1757         
1758         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1759         aop->coff = 0;
1760         if ((size = aop->size) <= 1)
1761                 return ;
1762         size-- ;
1763         switch (aop->type) {
1764         case AOP_R0 :
1765         case AOP_R1 :
1766                 while (size--)
1767                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1768                 break;                  
1769         case AOP_DPTR :
1770         case AOP_DPTR2:
1771                 if (aop->type == AOP_DPTR2)
1772                 {
1773                         genSetDPTR(1);
1774                 } 
1775                 while (size--)
1776                 {
1777                         pic14_emitcode("lcall","__decdptr");
1778                 }
1779                 
1780                 if (aop->type == AOP_DPTR2)
1781                 {
1782                         genSetDPTR(0);
1783                 }
1784                 break;
1785                 
1786         }
1787         
1788 }
1789
1790
1791 #if 0
1792 /*-----------------------------------------------------------------*/
1793 /* opIsGptr: returns non-zero if the passed operand is             */
1794 /* a generic pointer type.                                         */
1795 /*-----------------------------------------------------------------*/ 
1796 static int opIsGptr(operand *op)
1797 {
1798         sym_link *type = operandType(op);
1799         
1800         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1801         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1802         {
1803                 return 1;
1804         }
1805         return 0;          
1806 }
1807 #endif
1808
1809 /*-----------------------------------------------------------------*/
1810 /* pic14_getDataSize - get the operand data size                   */
1811 /*-----------------------------------------------------------------*/
1812 int pic14_getDataSize(operand *op)
1813 {
1814         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1815         
1816         
1817         return AOP_SIZE(op);
1818         
1819         // tsd- in the pic port, the genptr size is 1, so this code here
1820         // fails. ( in the 8051 port, the size was 4).
1821 #if 0
1822         int size;
1823         size = AOP_SIZE(op);
1824         if (size == GPTRSIZE)
1825         {
1826                 sym_link *type = operandType(op);
1827                 if (IS_GENPTR(type))
1828                 {
1829                         /* generic pointer; arithmetic operations
1830                         * should ignore the high byte (pointer type).
1831                         */
1832                         size--;
1833                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1834                 }
1835         }
1836         return size;
1837 #endif
1838 }
1839
1840 /*-----------------------------------------------------------------*/
1841 /* pic14_outAcc - output Acc                                       */
1842 /*-----------------------------------------------------------------*/
1843 void pic14_outAcc(operand *result)
1844 {
1845         int size,offset;
1846         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1847         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1848         
1849         
1850         size = pic14_getDataSize(result);
1851         if(size){
1852                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1853                 size--;
1854                 offset = 1;
1855                 /* unsigned or positive */
1856                 while(size--)
1857                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1858         }
1859         
1860 }
1861
1862 /*-----------------------------------------------------------------*/
1863 /* pic14_outBitC - output a bit C                                  */
1864 /*-----------------------------------------------------------------*/
1865 void pic14_outBitC(operand *result)
1866 {
1867         
1868         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1869         /* if the result is bit */
1870         if (AOP_TYPE(result) == AOP_CRY) 
1871                 aopPut(AOP(result),"c",0);
1872         else {
1873                 pic14_emitcode("clr","a  ; %d", __LINE__);
1874                 pic14_emitcode("rlc","a");
1875                 pic14_outAcc(result);
1876         }
1877 }
1878
1879 /*-----------------------------------------------------------------*/
1880 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1881 /*-----------------------------------------------------------------*/
1882 void pic14_toBoolean(operand *oper)
1883 {
1884         int size = AOP_SIZE(oper) - 1;
1885         int offset = 1;
1886         
1887         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1888         
1889         if ( AOP_TYPE(oper) != AOP_ACC) {
1890                 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1891         }
1892         while (size--) {
1893                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1894         }
1895 }
1896
1897
1898 /*-----------------------------------------------------------------*/
1899 /* genNot - generate code for ! operation                          */
1900 /*-----------------------------------------------------------------*/
1901 static void genNot (iCode *ic)
1902 {
1903         symbol *tlbl;
1904         int size;
1905
1906         FENTRY;
1907         
1908         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1909         /* assign asmOps to operand & result */
1910         aopOp (IC_LEFT(ic),ic,FALSE);
1911         aopOp (IC_RESULT(ic),ic,TRUE);
1912         
1913         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1914         /* if in bit space then a special case */
1915         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1916                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1917                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1918                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1919                 } else {
1920                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1921                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1922                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1923                 }
1924                 goto release;
1925         }
1926         
1927         size = AOP_SIZE(IC_LEFT(ic));
1928         if(size == 1) {
1929                 emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
1930                 emitpcode(POC_ANDLW,popGetLit(1));
1931                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1932                 goto release;
1933         }
1934         pic14_toBoolean(IC_LEFT(ic));
1935         
1936         tlbl = newiTempLabel(NULL);
1937         pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1938         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
1939         pic14_outBitC(IC_RESULT(ic));
1940         
1941 release:        
1942         /* release the aops */
1943         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1944         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1945 }
1946
1947
1948 /*-----------------------------------------------------------------*/
1949 /* genCpl - generate code for complement                                                   */
1950 /*-----------------------------------------------------------------*/
1951 static void genCpl (iCode *ic)
1952 {
1953         operand *left, *result;
1954         int size, offset=0;  
1955         
1956         FENTRY;
1957         
1958         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1959         aopOp((left = IC_LEFT(ic)),ic,FALSE);
1960         aopOp((result=IC_RESULT(ic)),ic,TRUE);
1961         
1962         /* if both are in bit space then 
1963         a special case */
1964         if (AOP_TYPE(result) == AOP_CRY &&
1965                 AOP_TYPE(left) == AOP_CRY ) { 
1966                 
1967                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1968                 pic14_emitcode("cpl","c"); 
1969                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1970                 goto release; 
1971         } 
1972         
1973         size = AOP_SIZE(result);
1974         while (size--) {
1975                 
1976                 if(AOP_TYPE(left) == AOP_ACC) 
1977                         emitpcode(POC_XORLW, popGetLit(0xff));
1978                 else
1979                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
1980                 
1981                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1982                 offset++;
1983         }
1984         
1985         
1986 release:
1987         /* release the aops */
1988         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1989         freeAsmop(result,NULL,ic,TRUE);
1990 }
1991
1992 /*-----------------------------------------------------------------*/
1993 /* genUminusFloat - unary minus for floating points                        */
1994 /*-----------------------------------------------------------------*/
1995 static void genUminusFloat(operand *op,operand *result)
1996 {
1997         int size ,offset =0 ;
1998         char *l;
1999         
2000         FENTRY;
2001
2002         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2003         /* for this we just need to flip the 
2004         first it then copy the rest in place */
2005         size = AOP_SIZE(op) - 1;
2006         l = aopGet(AOP(op),3,FALSE,FALSE);
2007         
2008         MOVA(l);          
2009         
2010         pic14_emitcode("cpl","acc.7");
2011         aopPut(AOP(result),"a",3);      
2012         
2013         while(size--) {
2014                 aopPut(AOP(result),
2015                         aopGet(AOP(op),offset,FALSE,FALSE),
2016                         offset);
2017                 offset++;
2018         }                
2019 }
2020
2021 /*-----------------------------------------------------------------*/
2022 /* genUminus - unary minus code generation                                                 */
2023 /*-----------------------------------------------------------------*/
2024 static void genUminus (iCode *ic)
2025 {
2026         int size, i;
2027         sym_link *optype, *rtype;
2028         
2029         FENTRY;
2030         
2031         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2032         /* assign asmops */
2033         aopOp(IC_LEFT(ic),ic,FALSE);
2034         aopOp(IC_RESULT(ic),ic,TRUE);
2035         
2036         /* if both in bit space then special
2037         case */
2038         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2039                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2040                 
2041                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2042                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2043                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2044                 
2045                 goto release; 
2046         } 
2047         
2048         optype = operandType(IC_LEFT(ic));
2049         rtype = operandType(IC_RESULT(ic));
2050         
2051         /* if float then do float stuff */
2052         if (IS_FLOAT(optype)) {
2053                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2054                 goto release;
2055         }
2056         
2057         /* otherwise subtract from zero by taking the 2's complement */
2058         size = AOP_SIZE(IC_LEFT(ic));
2059         
2060         for(i=0; i<size; i++) {
2061                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2062                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2063                 else {
2064                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2065                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2066                 }
2067         }
2068         
2069         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2070         for(i=1; i<size; i++) {
2071                 emitSKPNZ;
2072                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2073         }
2074         
2075 release:
2076         /* release the aops */
2077         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2078         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2079 }
2080
2081 /*-----------------------------------------------------------------*/
2082 /* saveRegisters - will look for a call and save the registers     */
2083 /*-----------------------------------------------------------------*/
2084 static void saveRegisters(iCode *lic) 
2085 {
2086         int i;
2087         iCode *ic;
2088         bitVect *rsave;
2089         sym_link *dtype;
2090         
2091         FENTRY;
2092
2093         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2094         /* look for call */
2095         for (ic = lic ; ic ; ic = ic->next) 
2096                 if (ic->op == CALL || ic->op == PCALL)
2097                         break;
2098                 
2099                 if (!ic) {
2100                         fprintf(stderr,"found parameter push with no function call\n");
2101                         return ;
2102                 }
2103                 
2104                 /* if the registers have been saved already then
2105                 do nothing */
2106                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2107                         return ;
2108                 
2109                         /* find the registers in use at this time 
2110                 and push them away to safety */
2111                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2112                         ic->rUsed);
2113                 
2114                 ic->regsSaved = 1;
2115                 if (options.useXstack) {
2116                         if (bitVectBitValue(rsave,R0_IDX))
2117                                 pic14_emitcode("mov","b,r0");
2118                         pic14_emitcode("mov","r0,%s",spname);
2119                         for (i = 0 ; i < pic14_nRegs ; i++) {
2120                                 if (bitVectBitValue(rsave,i)) {
2121                                         if (i == R0_IDX)
2122                                                 pic14_emitcode("mov","a,b");
2123                                         else
2124                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2125                                         pic14_emitcode("movx","@r0,a");
2126                                         pic14_emitcode("inc","r0");
2127                                 }
2128                         }
2129                         pic14_emitcode("mov","%s,r0",spname);
2130                         if (bitVectBitValue(rsave,R0_IDX))
2131                                 pic14_emitcode("mov","r0,b");     
2132                 }// else
2133                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2134                 //        if (bitVectBitValue(rsave,i))
2135                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2136                 //}
2137                 
2138                 dtype = operandType(IC_LEFT(ic));
2139                 if (currFunc && dtype && 
2140                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2141                         IFFUNC_ISISR(currFunc->type) &&
2142                         !ic->bankSaved) 
2143                         
2144                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2145                 
2146 }
2147 /*-----------------------------------------------------------------*/
2148 /* unsaveRegisters - pop the pushed registers                                      */
2149 /*-----------------------------------------------------------------*/
2150 static void unsaveRegisters (iCode *ic)
2151 {
2152         int i;
2153         bitVect *rsave;
2154         
2155         FENTRY;
2156
2157         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2158         /* find the registers in use at this time 
2159         and push them away to safety */
2160         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2161                 ic->rUsed);
2162         
2163         if (options.useXstack) {
2164                 pic14_emitcode("mov","r0,%s",spname); 
2165                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2166                         if (bitVectBitValue(rsave,i)) {
2167                                 pic14_emitcode("dec","r0");
2168                                 pic14_emitcode("movx","a,@r0");
2169                                 if (i == R0_IDX)
2170                                         pic14_emitcode("mov","b,a");
2171                                 else
2172                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2173                         }       
2174                         
2175                 }
2176                 pic14_emitcode("mov","%s,r0",spname);
2177                 if (bitVectBitValue(rsave,R0_IDX))
2178                         pic14_emitcode("mov","r0,b");
2179         } //else
2180         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2181         //      if (bitVectBitValue(rsave,i))
2182         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2183         //}
2184         
2185 }  
2186
2187
2188 /*-----------------------------------------------------------------*/
2189 /* pushSide -                            */
2190 /*-----------------------------------------------------------------*/
2191 static void pushSide(operand * oper, int size)
2192 {
2193 #if 0
2194         int offset = 0;
2195         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2196         while (size--) {
2197                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2198                 if (AOP_TYPE(oper) != AOP_REG &&
2199                         AOP_TYPE(oper) != AOP_DIR &&
2200                         strcmp(l,"a") ) {
2201                         pic14_emitcode("mov","a,%s",l);
2202                         pic14_emitcode("push","acc");
2203                 } else
2204                         pic14_emitcode("push","%s",l);
2205         }
2206 #endif
2207 }
2208
2209 /*-----------------------------------------------------------------*/
2210 /* assignResultValue -                           */
2211 /*-----------------------------------------------------------------*/
2212 static void assignResultValue(operand * oper)
2213 {
2214         int size = AOP_SIZE(oper);
2215         
2216         FENTRY;
2217
2218         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2219         
2220         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2221         
2222         while (size--) {
2223                 if (GpsuedoStkPtr++)
2224                         emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2225                 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2226         }
2227 }
2228
2229
2230 /*-----------------------------------------------------------------*/
2231 /* genIpush - genrate code for pushing this gets a little complex  */
2232 /*-----------------------------------------------------------------*/
2233 static void genIpush (iCode *ic)
2234 {
2235         FENTRY;
2236         
2237         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2238 #if 0
2239         int size, offset = 0 ;
2240         char *l;
2241         
2242         
2243         /* if this is not a parm push : ie. it is spill push 
2244         and spill push is always done on the local stack */
2245         if (!ic->parmPush) {
2246                 
2247                 /* and the item is spilt then do nothing */
2248                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2249                         return ;
2250                 
2251                 aopOp(IC_LEFT(ic),ic,FALSE);
2252                 size = AOP_SIZE(IC_LEFT(ic));
2253                 /* push it on the stack */
2254                 while(size--) {
2255                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2256                         if (*l == '#') {
2257                                 MOVA(l);
2258                                 l = "acc";
2259                         }
2260                         pic14_emitcode("push","%s",l);
2261                 }
2262                 return ;                
2263         }
2264         
2265         /* this is a paramter push: in this case we call
2266         the routine to find the call and save those
2267         registers that need to be saved */   
2268         saveRegisters(ic);
2269         
2270         /* then do the push */
2271         aopOp(IC_LEFT(ic),ic,FALSE);
2272         
2273         
2274         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2275         size = AOP_SIZE(IC_LEFT(ic));
2276         
2277         while (size--) {
2278                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2279                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2280                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2281                         strcmp(l,"a") ) {
2282                         pic14_emitcode("mov","a,%s",l);
2283                         pic14_emitcode("push","acc");
2284                 } else
2285                         pic14_emitcode("push","%s",l);
2286         }         
2287         
2288         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2289 #endif
2290 }
2291
2292 /*-----------------------------------------------------------------*/
2293 /* genIpop - recover the registers: can happen only for spilling   */
2294 /*-----------------------------------------------------------------*/
2295 static void genIpop (iCode *ic)
2296 {
2297         FENTRY;
2298
2299         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2300 #if 0
2301         int size,offset ;
2302         
2303         
2304         /* if the temp was not pushed then */
2305         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2306                 return ;
2307         
2308         aopOp(IC_LEFT(ic),ic,FALSE);
2309         size = AOP_SIZE(IC_LEFT(ic));
2310         offset = (size-1);
2311         while (size--) 
2312                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2313                 FALSE,TRUE));
2314         
2315         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2316 #endif
2317 }
2318
2319 /*-----------------------------------------------------------------*/
2320 /* unsaverbank - restores the resgister bank from stack                    */
2321 /*-----------------------------------------------------------------*/
2322 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2323 {
2324         FENTRY;
2325
2326         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2327 #if 0
2328         int i;
2329         asmop *aop ;
2330         regs *r = NULL;
2331         
2332         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2333         if (popPsw) {
2334                 if (options.useXstack) {
2335                         aop = newAsmop(0);
2336                         r = getFreePtr(ic,&aop,FALSE);
2337                         
2338                         
2339                         pic14_emitcode("mov","%s,_spx",r->name);
2340                         pic14_emitcode("movx","a,@%s",r->name);
2341                         pic14_emitcode("mov","psw,a");
2342                         pic14_emitcode("dec","%s",r->name);
2343                         
2344                 }else
2345                         pic14_emitcode ("pop","psw");
2346         }
2347         
2348         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2349                 if (options.useXstack) {           
2350                         pic14_emitcode("movx","a,@%s",r->name);
2351                         //pic14_emitcode("mov","(%s+%d),a",
2352                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2353                         pic14_emitcode("dec","%s",r->name);
2354                         
2355                 } else 
2356                         pic14_emitcode("pop",""); //"(%s+%d)",
2357                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2358         }
2359         
2360         if (options.useXstack) {
2361                 
2362                 pic14_emitcode("mov","_spx,%s",r->name);
2363                 freeAsmop(NULL,aop,ic,TRUE);
2364                 
2365         }
2366 #endif 
2367 }
2368
2369 /*-----------------------------------------------------------------*/
2370 /* saverbank - saves an entire register bank on the stack                  */
2371 /*-----------------------------------------------------------------*/
2372 static void saverbank (int bank, iCode *ic, bool pushPsw)
2373 {
2374         FENTRY;
2375
2376         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2377 #if 0
2378         int i;
2379         asmop *aop ;
2380         regs *r = NULL;
2381         
2382         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2383         if (options.useXstack) {
2384                 
2385                 aop = newAsmop(0);
2386                 r = getFreePtr(ic,&aop,FALSE);  
2387                 pic14_emitcode("mov","%s,_spx",r->name);
2388                 
2389         }
2390         
2391         for (i = 0 ; i < pic14_nRegs ;i++) {
2392                 if (options.useXstack) {
2393                         pic14_emitcode("inc","%s",r->name);
2394                         //pic14_emitcode("mov","a,(%s+%d)",
2395                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2396                         pic14_emitcode("movx","@%s,a",r->name);                 
2397                 } else 
2398                         pic14_emitcode("push","");// "(%s+%d)",
2399                 //regspic14[i].base,8*bank+regspic14[i].offset);
2400         }
2401         
2402         if (pushPsw) {
2403                 if (options.useXstack) {
2404                         pic14_emitcode("mov","a,psw");
2405                         pic14_emitcode("movx","@%s,a",r->name); 
2406                         pic14_emitcode("inc","%s",r->name);
2407                         pic14_emitcode("mov","_spx,%s",r->name);                 
2408                         freeAsmop (NULL,aop,ic,TRUE);
2409                         
2410                 } else
2411                         pic14_emitcode("push","psw");
2412                 
2413                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2414         }
2415         ic->bankSaved = 1;
2416 #endif
2417 }
2418
2419 /*-----------------------------------------------------------------*/
2420 /* genCall - generates a call statement                                                    */
2421 /*-----------------------------------------------------------------*/
2422 static void genCall (iCode *ic)
2423 {
2424         sym_link *dtype;         
2425         symbol *sym;
2426         unsigned char *name;
2427         int isExtern;
2428         
2429         FENTRY;
2430
2431         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2432         
2433         /* if caller saves & we have not saved then */
2434         if (!ic->regsSaved)
2435                 saveRegisters(ic);
2436         
2437                 /* if we are calling a function that is not using
2438                 the same register bank then we need to save the
2439         destination registers on the stack */
2440         dtype = operandType(IC_LEFT(ic));
2441         if (currFunc && dtype && 
2442                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2443                 IFFUNC_ISISR(currFunc->type) &&
2444                 !ic->bankSaved) 
2445                 
2446                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2447         
2448         /* if send set is not empty the assign */
2449         if (_G.sendSet) {
2450                 iCode *sic;
2451                 /* For the Pic port, there is no data stack.
2452                 * So parameters passed to functions are stored
2453                 * in registers. (The pCode optimizer will get
2454                 * rid of most of these :).
2455                 */
2456                 int psuedoStkPtr=-1;
2457                 int firstTimeThruLoop = 1;
2458                 
2459                 _G.sendSet = reverseSet(_G.sendSet);
2460                 
2461                 /* First figure how many parameters are getting passed */
2462                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2463                 sic = setNextItem(_G.sendSet)) {
2464                         
2465                         aopOp(IC_LEFT(sic),sic,FALSE);
2466                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2467                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2468                 }
2469                 
2470                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2471                 sic = setNextItem(_G.sendSet)) {
2472                         int size, offset = 0;
2473                         
2474                         aopOp(IC_LEFT(sic),sic,FALSE);
2475                         size = AOP_SIZE(IC_LEFT(sic));
2476                         
2477                         while (size--) {
2478                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2479                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2480                                 
2481                                 if(!firstTimeThruLoop) {
2482                                         /* If this is not the first time we've been through the loop
2483                                         * then we need to save the parameter in a temporary
2484                                         * register. The last byte of the last parameter is
2485                                         * passed in W. */
2486                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2487                                         
2488                                 }
2489                                 firstTimeThruLoop=0;
2490                                 
2491                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2492                                 offset++;
2493                         }
2494                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2495                 }
2496                 _G.sendSet = NULL;
2497         }
2498         /* make the call */
2499         sym = OP_SYMBOL(IC_LEFT(ic));
2500         name = sym->rname[0] ? sym->rname : sym->name;
2501         isExtern = IS_EXTERN(sym->etype);
2502         if (isExtern) {
2503                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2504         }
2505         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2506         if (isExtern) {
2507                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2508         }
2509         GpsuedoStkPtr=0;
2510         /* if we need assign a result value */
2511         if ((IS_ITEMP(IC_RESULT(ic)) && 
2512                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2513                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2514                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2515                 
2516                 _G.accInUse++;
2517                 aopOp(IC_RESULT(ic),ic,FALSE);
2518                 _G.accInUse--;
2519                 
2520                 assignResultValue(IC_RESULT(ic));
2521                 
2522                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2523                         AopType(AOP_TYPE(IC_RESULT(ic))));
2524                 
2525                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2526         }
2527         
2528         /* adjust the stack for parameters if 
2529         required */
2530         if (ic->parmBytes) {
2531                 int i;
2532                 if (ic->parmBytes > 3) {
2533                         pic14_emitcode("mov","a,%s",spname);
2534                         pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2535                         pic14_emitcode("mov","%s,a",spname);
2536                 } else 
2537                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2538                                 pic14_emitcode("dec","%s",spname);
2539                         
2540         }
2541         
2542         /* if register bank was saved then pop them */
2543         if (ic->bankSaved)
2544                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2545         
2546         /* if we hade saved some registers then unsave them */
2547         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2548                 unsaveRegisters (ic);
2549         
2550         
2551 }
2552
2553 /*-----------------------------------------------------------------*/
2554 /* genPcall - generates a call by pointer statement                        */
2555 /*-----------------------------------------------------------------*/
2556 static void genPcall (iCode *ic)
2557 {
2558         sym_link *dtype;
2559         symbol *albl = newiTempLabel(NULL);
2560         symbol *blbl = newiTempLabel(NULL);
2561         PIC_OPCODE poc;
2562         pCodeOp *pcop;
2563         operand *left;
2564         
2565         FENTRY;
2566
2567         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2568         /* if caller saves & we have not saved then */
2569         if (!ic->regsSaved)
2570                 saveRegisters(ic);
2571         
2572                 /* if we are calling a function that is not using
2573                 the same register bank then we need to save the
2574         destination registers on the stack */
2575         dtype = operandType(IC_LEFT(ic));
2576         if (currFunc && dtype && 
2577                 IFFUNC_ISISR(currFunc->type) &&
2578                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2579                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2580         
2581         left = IC_LEFT(ic);
2582         aopOp(left,ic,FALSE);
2583         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2584         
2585         pushSide(IC_LEFT(ic), FPTRSIZE);
2586         
2587         /* if send set is not empty, assign parameters */
2588         if (_G.sendSet) {
2589                 
2590                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2591                 /* no way to pass args - W always gets used to make the call */
2592         }
2593         /* first idea - factor out a common helper function and call it.
2594         But don't know how to get it generated only once in its own block
2595         
2596         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2597                 char *rname;
2598                 char *buffer;
2599                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2600                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2601                 buffer = Safe_calloc(1,strlen(rname)+16);
2602                 sprintf(buffer, "%s_goto_helper", rname);
2603                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2604                 free(buffer);
2605         }
2606         */
2607         emitpcode(POC_CALL,popGetLabel(albl->key));
2608         pcop = popGetLabel(blbl->key);
2609         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2610         emitpcode(POC_GOTO,pcop);
2611         emitpLabel(albl->key);
2612         
2613         poc = ( aop_isLitLike (AOP(left)) ? POC_MOVLW : POC_MOVFW );
2614         
2615         emitpcode(poc,popGetAddr(AOP(left),1,0));
2616         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2617         emitpcode(poc,popGetAddr(AOP(left),0,0));
2618         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2619         
2620         emitpLabel(blbl->key);
2621         
2622         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2623         
2624         /* if we need to assign a result value */
2625         if ((IS_ITEMP(IC_RESULT(ic)) &&
2626                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2627                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2628                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2629                 
2630                 _G.accInUse++;
2631                 aopOp(IC_RESULT(ic),ic,FALSE);
2632                 _G.accInUse--;
2633                 
2634                 assignResultValue(IC_RESULT(ic));
2635                 
2636                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2637         }
2638         
2639         /* if register bank was saved then unsave them */
2640         if (currFunc && dtype && 
2641                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2642                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2643         
2644                 /* if we hade saved some registers then
2645         unsave them */
2646         if (ic->regsSaved)
2647                 unsaveRegisters (ic);
2648         
2649 }
2650
2651 /*-----------------------------------------------------------------*/
2652 /* resultRemat - result  is rematerializable                                       */
2653 /*-----------------------------------------------------------------*/
2654 static int resultRemat (iCode *ic)
2655 {
2656         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2657         FENTRY;
2658
2659         if (SKIP_IC(ic) || ic->op == IFX)
2660                 return 0;
2661         
2662         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2663                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2664                 if (sym->remat && !POINTER_SET(ic)) 
2665                         return 1;
2666         }
2667         
2668         return 0;
2669 }
2670
2671 #if defined(__BORLANDC__) || defined(_MSC_VER)
2672 #define STRCASECMP stricmp
2673 #else
2674 #define STRCASECMP strcasecmp
2675 #endif
2676
2677 #if 0
2678 /*-----------------------------------------------------------------*/
2679 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2680 /*-----------------------------------------------------------------*/
2681 static bool inExcludeList(char *s)
2682 {
2683         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2684         int i =0;
2685         
2686         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2687         if (options.excludeRegs[i] &&
2688                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2689                 return FALSE ;
2690         
2691         for ( i = 0 ; options.excludeRegs[i]; i++) {
2692                 if (options.excludeRegs[i] &&
2693                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2694                         return TRUE;
2695         }
2696         return FALSE ;
2697 }
2698 #endif
2699
2700 /*-----------------------------------------------------------------*/
2701 /* genFunction - generated code for function entry                                 */
2702 /*-----------------------------------------------------------------*/
2703 static void genFunction (iCode *ic)
2704 {
2705         symbol *sym;
2706         sym_link *ftype;
2707         
2708         FENTRY;
2709
2710         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2711         
2712         labelOffset += (max_key+4);
2713         max_key=0;
2714         GpsuedoStkPtr=0;
2715         _G.nRegsSaved = 0;
2716         /* create the function header */
2717         pic14_emitcode(";","-----------------------------------------");
2718         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2719         pic14_emitcode(";","-----------------------------------------");
2720         
2721         pic14_emitcode("","%s:",sym->rname);
2722         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2723         
2724         ftype = operandType(IC_LEFT(ic));
2725         
2726         /* if critical function then turn interrupts off */
2727         if (IFFUNC_ISCRITICAL(ftype))
2728                 pic14_emitcode("clr","ea");
2729         
2730                 /* here we need to generate the equates for the
2731         register bank if required */
2732 #if 0
2733         if (FUNC_REGBANK(ftype) != rbank) {
2734                 int i ;
2735                 
2736                 rbank = FUNC_REGBANK(ftype);
2737                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2738                         if (strcmp(regspic14[i].base,"0") == 0)
2739                                 pic14_emitcode("","%s = 0x%02x",
2740                                 regspic14[i].dname,
2741                                 8*rbank+regspic14[i].offset);
2742                         else
2743                                 pic14_emitcode ("","%s = %s + 0x%02x",
2744                                 regspic14[i].dname,
2745                                 regspic14[i].base,
2746                                 8*rbank+regspic14[i].offset);
2747                 }
2748         }
2749 #endif
2750         
2751         /* if this is an interrupt service routine */
2752         if (IFFUNC_ISISR(sym->type)) {
2753         /*  already done in pic14createInterruptVect() - delete me
2754         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2755         emitpcodeNULLop(POC_NOP);
2756         emitpcodeNULLop(POC_NOP);
2757         emitpcodeNULLop(POC_NOP);
2758                 */
2759                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2760                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2761                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2762                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2763                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2764                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2765                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2766                 
2767                 pBlockConvert2ISR(pb);
2768 #if 0  
2769                 if (!inExcludeList("acc"))              
2770                         pic14_emitcode ("push","acc");  
2771                 if (!inExcludeList("b"))
2772                         pic14_emitcode ("push","b");
2773                 if (!inExcludeList("dpl"))
2774                         pic14_emitcode ("push","dpl");
2775                 if (!inExcludeList("dph"))
2776                         pic14_emitcode ("push","dph");
2777                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2778                 {
2779                         pic14_emitcode ("push", "dpx");
2780                         /* Make sure we're using standard DPTR */
2781                         pic14_emitcode ("push", "dps");
2782                         pic14_emitcode ("mov", "dps, #0x00");
2783                         if (options.stack10bit)
2784                         { 
2785                                 /* This ISR could conceivably use DPTR2. Better save it. */
2786                                 pic14_emitcode ("push", "dpl1");
2787                                 pic14_emitcode ("push", "dph1");
2788                                 pic14_emitcode ("push", "dpx1");
2789                         }
2790                 }
2791                 /* if this isr has no bank i.e. is going to
2792                 run with bank 0 , then we need to save more
2793                 registers :-) */
2794                 if (!FUNC_REGBANK(sym->type)) {
2795                         
2796                 /* if this function does not call any other
2797                 function then we can be economical and
2798                         save only those registers that are used */
2799                         if (! IFFUNC_HASFCALL(sym->type)) {
2800                                 int i;
2801                                 
2802                                 /* if any registers used */
2803                                 if (sym->regsUsed) {
2804                                         /* save the registers used */
2805                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2806                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2807                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2808                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2809                                         }
2810                                 }
2811                                 
2812                         } else {
2813                         /* this function has    a function call cannot
2814                         determines register usage so we will have the
2815                                 entire bank */
2816                                 saverbank(0,ic,FALSE);
2817                         }       
2818                 }
2819 #endif
2820         } else {
2821         /* if callee-save to be used for this function
2822                 then save the registers being used in this function */
2823                 if (IFFUNC_CALLEESAVES(sym->type)) {
2824                         int i;
2825                         
2826                         /* if any registers used */
2827                         if (sym->regsUsed) {
2828                                 /* save the registers used */
2829                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2830                                         if (bitVectBitValue(sym->regsUsed,i) ||
2831                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2832                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2833                                                 _G.nRegsSaved++;
2834                                         }
2835                                 }
2836                         }
2837                 }
2838         }
2839         
2840         /* set the register bank to the desired value */
2841         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2842                 pic14_emitcode("push","psw");
2843                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
2844         }
2845         
2846         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2847                 
2848                 if (options.useXstack) {
2849                         pic14_emitcode("mov","r0,%s",spname);
2850                         pic14_emitcode("mov","a,_bp");
2851                         pic14_emitcode("movx","@r0,a");
2852                         pic14_emitcode("inc","%s",spname);
2853                 }
2854                 else
2855                 {
2856                         /* set up the stack */
2857                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
2858                 }
2859                 pic14_emitcode ("mov","_bp,%s",spname);
2860         }
2861         
2862         /* adjust the stack for the function */
2863         if (sym->stack) {
2864                 
2865                 int i = sym->stack;
2866                 if (i > 256 ) 
2867                         werror(W_STACK_OVERFLOW,sym->name);
2868                 
2869                 if (i > 3 && sym->recvSize < 4) {                
2870                         
2871                         pic14_emitcode ("mov","a,sp");
2872                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2873                         pic14_emitcode ("mov","sp,a");
2874                         
2875                 }
2876                 else
2877                         while(i--)
2878                                 pic14_emitcode("inc","sp");
2879         }
2880         
2881         if (sym->xstack) {
2882                 
2883                 pic14_emitcode ("mov","a,_spx");
2884                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2885                 pic14_emitcode ("mov","_spx,a");
2886         }
2887         
2888 }
2889
2890 /*-----------------------------------------------------------------*/
2891 /* genEndFunction - generates epilogue for functions                       */
2892 /*-----------------------------------------------------------------*/
2893 static void genEndFunction (iCode *ic)
2894 {
2895         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2896         
2897         FENTRY;
2898
2899         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2900         
2901         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2902         {
2903                 pic14_emitcode ("mov","%s,_bp",spname);
2904         }
2905         
2906         /* if use external stack but some variables were
2907         added to the local stack then decrement the
2908         local stack */
2909         if (options.useXstack && sym->stack) {    
2910                 pic14_emitcode("mov","a,sp");
2911                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2912                 pic14_emitcode("mov","sp,a");
2913         }
2914         
2915         
2916         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2917                 if (options.useXstack) {
2918                         pic14_emitcode("mov","r0,%s",spname);
2919                         pic14_emitcode("movx","a,@r0");
2920                         pic14_emitcode("mov","_bp,a");
2921                         pic14_emitcode("dec","%s",spname);
2922                 }
2923                 else
2924                 {
2925                         pic14_emitcode ("pop","_bp");
2926                 }
2927         }
2928         
2929         /* restore the register bank    */        
2930         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2931                 pic14_emitcode ("pop","psw");
2932         
2933         if (IFFUNC_ISISR(sym->type)) {
2934                 
2935                 /* now we need to restore the registers */
2936                 /* if this isr has no bank i.e. is going to
2937                 run with bank 0 , then we need to save more
2938 registers :-) */
2939                 if (!FUNC_REGBANK(sym->type)) {
2940                         
2941                 /* if this function does not call any other
2942                 function then we can be economical and
2943                         save only those registers that are used */
2944                         if (! IFFUNC_HASFCALL(sym->type)) {
2945                                 int i;
2946                                 
2947                                 /* if any registers used */
2948                                 if (sym->regsUsed) {
2949                                         /* save the registers used */
2950                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2951                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2952                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2953                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2954                                         }
2955                                 }
2956                                 
2957                         } else {
2958                         /* this function has    a function call cannot
2959                         determines register usage so we will have the
2960                                 entire bank */
2961                                 unsaverbank(0,ic,FALSE);
2962                         }       
2963                 }
2964 #if 0
2965                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2966                 {
2967                         if (options.stack10bit)
2968                         {
2969                                 pic14_emitcode ("pop", "dpx1");
2970                                 pic14_emitcode ("pop", "dph1");
2971                                 pic14_emitcode ("pop", "dpl1");
2972                         } 
2973                         pic14_emitcode ("pop", "dps");
2974                         pic14_emitcode ("pop", "dpx");
2975                 }
2976                 if (!inExcludeList("dph"))
2977                         pic14_emitcode ("pop","dph");
2978                 if (!inExcludeList("dpl"))
2979                         pic14_emitcode ("pop","dpl");
2980                 if (!inExcludeList("b"))
2981                         pic14_emitcode ("pop","b");
2982                 if (!inExcludeList("acc"))
2983                         pic14_emitcode ("pop","acc");
2984                 
2985                 if (IFFUNC_ISCRITICAL(sym->type))
2986                         pic14_emitcode("setb","ea");
2987 #endif
2988                 
2989                 /* if debug then send end of function */
2990                 /*      if (options.debug && currFunc) { */
2991                 if (currFunc) {
2992                         debugFile->writeEndFunction (currFunc, ic, 1);
2993                 }
2994                 
2995                 pic14_emitcode ("reti","");
2996                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
2997                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
2998                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2999                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3000                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3001                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3002                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3003                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3004                 emitpcodeNULLop(POC_RETFIE);
3005         }
3006         else {
3007                 if (IFFUNC_ISCRITICAL(sym->type))
3008                         pic14_emitcode("setb","ea");
3009                 
3010                 if (IFFUNC_CALLEESAVES(sym->type)) {
3011                         int i;
3012                         
3013                         /* if any registers used */
3014                         if (sym->regsUsed) {
3015                                 /* save the registers used */
3016                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3017                                         if (bitVectBitValue(sym->regsUsed,i) ||
3018                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3019                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3020                                 }
3021                         }
3022                         
3023                 }
3024                 
3025                 /* if debug then send end of function */
3026                 if (currFunc) {
3027                         debugFile->writeEndFunction (currFunc, ic, 1);
3028                 }
3029                 
3030                 pic14_emitcode ("return","");
3031                 emitpcodeNULLop(POC_RETURN);
3032                 
3033                 /* Mark the end of a function */
3034                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3035         }
3036         
3037 }
3038
3039 /*-----------------------------------------------------------------*/
3040 /* genRet - generate code for return statement                                     */
3041 /*-----------------------------------------------------------------*/
3042 static void genRet (iCode *ic)
3043 {
3044         int size,offset = 0 , pushed = 0;
3045         
3046         FENTRY;
3047
3048         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3049         /* if we have no return value then
3050         just generate the "ret" */
3051         if (!IC_LEFT(ic)) 
3052                 goto jumpret;           
3053         
3054                 /* we have something to return then
3055         move the return value into place */
3056         aopOp(IC_LEFT(ic),ic,FALSE);
3057         size = AOP_SIZE(IC_LEFT(ic));
3058         
3059         while (size--) {
3060                 char *l ;
3061                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3062                         /* #NOCHANGE */
3063                         l = aopGet(AOP(IC_LEFT(ic)),offset++,
3064                                 FALSE,TRUE);
3065                         pic14_emitcode("push","%s",l);
3066                         pushed++;
3067                 } else {
3068                         l = aopGet(AOP(IC_LEFT(ic)),offset,
3069                                 FALSE,FALSE);
3070                         if (strcmp(fReturn[offset],l)) {
3071                                 if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
3072                                         AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
3073                                         ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3074                                         ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3075                                         emitpcode(POC_MOVLW, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
3076                                 }else {
3077                                         emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3078                                 }
3079                                 if(size) {
3080                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
3081                                 }
3082                                 offset++;
3083                         }
3084                 }
3085         }
3086         
3087         if (pushed) {
3088                 while(pushed) {
3089                         pushed--;
3090                         if (strcmp(fReturn[pushed],"a"))
3091                                 pic14_emitcode("pop",fReturn[pushed]);
3092                         else
3093                                 pic14_emitcode("pop","acc");
3094                 }
3095         }
3096         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3097         
3098 jumpret:
3099         /* generate a jump to the return label
3100         if the next is not the return statement */
3101         if (!(ic->next && ic->next->op == LABEL &&
3102                 IC_LABEL(ic->next) == returnLabel)) {
3103                 
3104                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3105                 pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3106         }
3107         
3108 }
3109
3110 /*-----------------------------------------------------------------*/
3111 /* genLabel - generates a label                                                                    */
3112 /*-----------------------------------------------------------------*/
3113 static void genLabel (iCode *ic)
3114 {
3115         FENTRY;
3116
3117         /* special case never generate */
3118         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3119         if (IC_LABEL(ic) == entryLabel)
3120                 return ;
3121         
3122         emitpLabel(IC_LABEL(ic)->key);
3123         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3124 }
3125
3126 /*-----------------------------------------------------------------*/
3127 /* genGoto - generates a goto                                                                      */
3128 /*-----------------------------------------------------------------*/
3129 //tsd
3130 static void genGoto (iCode *ic)
3131 {
3132         FENTRY;
3133
3134         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3135         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3136 }
3137
3138
3139 /*-----------------------------------------------------------------*/
3140 /* genMultbits :- multiplication of bits                                                   */
3141 /*-----------------------------------------------------------------*/
3142 static void genMultbits (operand *left, 
3143                                                  operand *right, 
3144                                                  operand *result)
3145 {
3146         FENTRY;
3147         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3148         
3149         if(!pic14_sameRegs(AOP(result),AOP(right)))
3150                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3151         
3152         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3153         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3154         emitpcode(POC_BCF,  popGet(AOP(result),0));
3155         
3156 }
3157
3158
3159 /*-----------------------------------------------------------------*/
3160 /* genMultOneByte : 8 bit multiplication & division                        */
3161 /*-----------------------------------------------------------------*/
3162 static void genMultOneByte (operand *left,
3163                                                         operand *right,
3164                                                         operand *result)
3165 {
3166         sym_link *opetype = operandType(result);
3167         
3168         // symbol *lbl ;
3169         int size,offset;
3170         
3171         FENTRY;
3172         
3173         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3174         DEBUGpic14_AopType(__LINE__,left,right,result);
3175         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3176         
3177         /* (if two literals, the value is computed before) */
3178         /* if one literal, literal on the right */
3179         if (AOP_TYPE(left) == AOP_LIT){
3180                 operand *t = right;
3181                 right = left;
3182                 left = t;
3183         }
3184         
3185         size = AOP_SIZE(result);
3186         if(size == 1) {
3187                 
3188                 if (AOP_TYPE(right) == AOP_LIT){
3189                         pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3190                                 aopGet(AOP(right),0,FALSE,FALSE), 
3191                                 aopGet(AOP(left),0,FALSE,FALSE), 
3192                                 aopGet(AOP(result),0,FALSE,FALSE));
3193                         pic14_emitcode("call","genMultLit");
3194                 } else {
3195                         pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3196                                 aopGet(AOP(right),0,FALSE,FALSE), 
3197                                 aopGet(AOP(left),0,FALSE,FALSE), 
3198                                 aopGet(AOP(result),0,FALSE,FALSE));
3199                         pic14_emitcode("call","genMult8X8_8");
3200                         
3201                 }
3202                 genMult8X8_8 (left, right,result);
3203                 
3204                 
3205                 /* signed or unsigned */
3206                 //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3207                 //l = aopGet(AOP(left),0,FALSE,FALSE);
3208                 //MOVA(l);               
3209                 //pic14_emitcode("mul","ab");
3210                 /* if result size = 1, mul signed = mul unsigned */
3211                 //aopPut(AOP(result),"a",0);
3212                 
3213         } else {        // (size > 1)
3214                 
3215                 pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3216                         aopGet(AOP(right),0,FALSE,FALSE), 
3217                         aopGet(AOP(left),0,FALSE,FALSE), 
3218                         aopGet(AOP(result),0,FALSE,FALSE));
3219                 
3220                 if (SPEC_USIGN(opetype)){
3221                         pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3222                         genUMult8X8_16 (left, right, result, NULL);
3223                         
3224                         if (size > 2) {
3225                                 /* for filling the MSBs */
3226                                 emitpcode(POC_CLRF,  popGet(AOP(result),2));
3227                                 emitpcode(POC_CLRF,  popGet(AOP(result),3));
3228                         }
3229                 }
3230                 else{
3231                         pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3232                         
3233                         pic14_emitcode("mov","a,b");
3234                         
3235                         /* adjust the MSB if left or right neg */
3236                         
3237                         /* if one literal */
3238                         if (AOP_TYPE(right) == AOP_LIT){
3239                                 pic14_emitcode("multiply ","right is a lit");
3240                                 /* AND literal negative */
3241                                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3242                                         /* adjust MSB (c==0 after mul) */
3243                                         pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3244                                 }
3245                         }
3246                         else{
3247                                 genSMult8X8_16 (left, right, result, NULL);
3248                         }
3249                         
3250                         if(size > 2){
3251                                 pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3252                                 /* get the sign */
3253                                 pic14_emitcode("rlc","a");
3254                                 pic14_emitcode("subb","a,acc");
3255                         }
3256                 }
3257                 
3258                 size -= 2;
3259                 offset = 2;
3260                 if (size > 0)
3261                         while (size--)
3262                                 pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3263                         //aopPut(AOP(result),"a",offset++);
3264         }
3265 }
3266
3267 /*-----------------------------------------------------------------*/
3268 /* genMult - generates code for multiplication                                     */
3269 /*-----------------------------------------------------------------*/
3270 static void genMult (iCode *ic)
3271 {
3272         operand *left = IC_LEFT(ic);
3273         operand *right = IC_RIGHT(ic);
3274         operand *result= IC_RESULT(ic); 
3275         
3276         FENTRY;
3277
3278         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3279         /* assign the amsops */
3280         aopOp (left,ic,FALSE);
3281         aopOp (right,ic,FALSE);
3282         aopOp (result,ic,TRUE);
3283         
3284         DEBUGpic14_AopType(__LINE__,left,right,result);
3285         
3286         /* special cases first */
3287         /* both are bits */
3288         if (AOP_TYPE(left) == AOP_CRY &&
3289                 AOP_TYPE(right)== AOP_CRY) {
3290                 genMultbits(left,right,result);
3291                 goto release ;
3292         }
3293         
3294         /* if both are of size == 1 */
3295         if (AOP_SIZE(left) == 1 &&
3296                 AOP_SIZE(right) == 1 ) {
3297                 genMultOneByte(left,right,result);
3298                 goto release ;
3299         }
3300         
3301         pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3302         
3303         /* should have been converted to function call */
3304         //assert(0) ;
3305         
3306 release :
3307         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3308         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3309         freeAsmop(result,NULL,ic,TRUE); 
3310 }
3311
3312 /*-----------------------------------------------------------------*/
3313 /* genDivbits :- division of bits                                                                  */
3314 /*-----------------------------------------------------------------*/
3315 static void genDivbits (operand *left, 
3316                                                 operand *right, 
3317                                                 operand *result)
3318 {
3319         
3320         char *l;
3321         
3322         FENTRY;
3323
3324         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3325         /* the result must be bit */      
3326         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3327         l = aopGet(AOP(left),0,FALSE,FALSE);
3328         
3329         MOVA(l);          
3330         
3331         pic14_emitcode("div","ab");
3332         pic14_emitcode("rrc","a");
3333         aopPut(AOP(result),"c",0);
3334 }
3335
3336 /*-----------------------------------------------------------------*/
3337 /* genDivOneByte : 8 bit division                                                                  */
3338 /*-----------------------------------------------------------------*/
3339 static void genDivOneByte (operand *left,
3340                                                    operand *right,
3341                                                    operand *result)
3342 {
3343         sym_link *opetype = operandType(result);
3344         char *l ;
3345         symbol *lbl ;
3346         int size,offset;
3347         
3348         FENTRY;
3349         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3350         size = AOP_SIZE(result) - 1;
3351         offset = 1;
3352         /* signed or unsigned */
3353         if (SPEC_USIGN(opetype)) {
3354                 /* unsigned is easy */
3355                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3356                 l = aopGet(AOP(left),0,FALSE,FALSE);
3357                 MOVA(l);                
3358                 pic14_emitcode("div","ab");
3359                 aopPut(AOP(result),"a",0);
3360                 while (size--)
3361                         aopPut(AOP(result),zero,offset++);
3362                 return ;
3363         }
3364         
3365         /* signed is a little bit more difficult */
3366         
3367         /* save the signs of the operands */
3368         l = aopGet(AOP(left),0,FALSE,FALSE);      
3369         MOVA(l);          
3370         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3371         pic14_emitcode("push","acc"); /* save it on the stack */
3372         
3373         /* now sign adjust for both left & right */
3374         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3375         MOVA(l);                 
3376         lbl = newiTempLabel(NULL);
3377         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3378         pic14_emitcode("cpl","a");   
3379         pic14_emitcode("inc","a");
3380         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3381         pic14_emitcode("mov","b,a");
3382         
3383         /* sign adjust left side */
3384         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3385         MOVA(l);
3386         
3387         lbl = newiTempLabel(NULL);
3388         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3389         pic14_emitcode("cpl","a");
3390         pic14_emitcode("inc","a");
3391         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3392         
3393         /* now the division */
3394         pic14_emitcode("div","ab");
3395         /* we are interested in the lower order
3396         only */
3397         pic14_emitcode("mov","b,a");
3398         lbl = newiTempLabel(NULL);
3399         pic14_emitcode("pop","acc");     
3400         /* if there was an over flow we don't 
3401         adjust the sign of the result */
3402         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3403         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3404         CLRC;
3405         pic14_emitcode("clr","a");
3406         pic14_emitcode("subb","a,b");
3407         pic14_emitcode("mov","b,a");
3408         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3409         
3410         /* now we are done */
3411         aopPut(AOP(result),"b",0);
3412         if(size > 0){
3413                 pic14_emitcode("mov","c,b.7");
3414                 pic14_emitcode("subb","a,acc");   
3415         }
3416         while (size--)
3417                 aopPut(AOP(result),"a",offset++);
3418         
3419 }
3420
3421 /*-----------------------------------------------------------------*/
3422 /* genDiv - generates code for division                                                    */
3423 /*-----------------------------------------------------------------*/
3424 static void genDiv (iCode *ic)
3425 {
3426         operand *left = IC_LEFT(ic);
3427         operand *right = IC_RIGHT(ic);
3428         operand *result= IC_RESULT(ic); 
3429         
3430         FENTRY;
3431         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3432         /* assign the amsops */
3433         aopOp (left,ic,FALSE);
3434         aopOp (right,ic,FALSE);
3435         aopOp (result,ic,TRUE);
3436         
3437         /* special cases first */
3438         /* both are bits */
3439         if (AOP_TYPE(left) == AOP_CRY &&
3440                 AOP_TYPE(right)== AOP_CRY) {
3441                 genDivbits(left,right,result);
3442                 goto release ;
3443         }
3444         
3445         /* if both are of size == 1 */
3446         if (AOP_SIZE(left) == 1 &&
3447                 AOP_SIZE(right) == 1 ) {
3448                 genDivOneByte(left,right,result);
3449                 goto release ;
3450         }
3451         
3452         /* should have been converted to function call */
3453         assert(0);
3454 release :
3455         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3456         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3457         freeAsmop(result,NULL,ic,TRUE); 
3458 }
3459
3460 /*-----------------------------------------------------------------*/
3461 /* genModbits :- modulus of bits                                                                   */
3462 /*-----------------------------------------------------------------*/
3463 static void genModbits (operand *left, 
3464                                                 operand *right, 
3465                                                 operand *result)
3466 {
3467         
3468         char *l;
3469         
3470         FENTRY;
3471         /* the result must be bit */      
3472         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3473         l = aopGet(AOP(left),0,FALSE,FALSE);
3474         
3475         MOVA(l);
3476         
3477         pic14_emitcode("div","ab");
3478         pic14_emitcode("mov","a,b");
3479         pic14_emitcode("rrc","a");
3480         aopPut(AOP(result),"c",0);
3481 }
3482
3483 /*-----------------------------------------------------------------*/
3484 /* genModOneByte : 8 bit modulus                                                                   */
3485 /*-----------------------------------------------------------------*/
3486 static void genModOneByte (operand *left,
3487                                                    operand *right,
3488                                                    operand *result)
3489 {
3490         sym_link *opetype = operandType(result);
3491         char *l ;
3492         symbol *lbl ;
3493         
3494         FENTRY;
3495         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3496         /* signed or unsigned */
3497         if (SPEC_USIGN(opetype)) {
3498                 /* unsigned is easy */
3499                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3500                 l = aopGet(AOP(left),0,FALSE,FALSE);
3501                 MOVA(l);        
3502                 pic14_emitcode("div","ab");
3503                 aopPut(AOP(result),"b",0);
3504                 return ;
3505         }
3506         
3507         /* signed is a little bit more difficult */
3508         
3509         /* save the signs of the operands */
3510         l = aopGet(AOP(left),0,FALSE,FALSE);      
3511         MOVA(l);
3512         
3513         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3514         pic14_emitcode("push","acc"); /* save it on the stack */
3515         
3516         /* now sign adjust for both left & right */
3517         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3518         MOVA(l);
3519         
3520         lbl = newiTempLabel(NULL);
3521         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3522         pic14_emitcode("cpl","a");   
3523         pic14_emitcode("inc","a");
3524         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3525         pic14_emitcode("mov","b,a"); 
3526         
3527         /* sign adjust left side */
3528         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3529         MOVA(l);
3530         
3531         lbl = newiTempLabel(NULL);
3532         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3533         pic14_emitcode("cpl","a");   
3534         pic14_emitcode("inc","a");
3535         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3536         
3537         /* now the multiplication */
3538         pic14_emitcode("div","ab");
3539         /* we are interested in the lower order
3540         only */
3541         lbl = newiTempLabel(NULL);
3542         pic14_emitcode("pop","acc");     
3543         /* if there was an over flow we don't 
3544         adjust the sign of the result */
3545         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3546         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3547         CLRC ;
3548         pic14_emitcode("clr","a");
3549         pic14_emitcode("subb","a,b");
3550         pic14_emitcode("mov","b,a");
3551         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3552         
3553         /* now we are done */
3554         aopPut(AOP(result),"b",0);
3555         
3556 }
3557
3558 /*-----------------------------------------------------------------*/
3559 /* genMod - generates code for division                                                    */
3560 /*-----------------------------------------------------------------*/
3561 static void genMod (iCode *ic)
3562 {
3563         operand *left = IC_LEFT(ic);
3564         operand *right = IC_RIGHT(ic);
3565         operand *result= IC_RESULT(ic);  
3566         
3567         FENTRY;
3568         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3569         /* assign the amsops */
3570         aopOp (left,ic,FALSE);
3571         aopOp (right,ic,FALSE);
3572         aopOp (result,ic,TRUE);
3573         
3574         /* special cases first */
3575         /* both are bits */
3576         if (AOP_TYPE(left) == AOP_CRY &&
3577                 AOP_TYPE(right)== AOP_CRY) {
3578                 genModbits(left,right,result);
3579                 goto release ;
3580         }
3581         
3582         /* if both are of size == 1 */
3583         if (AOP_SIZE(left) == 1 &&
3584                 AOP_SIZE(right) == 1 ) {
3585                 genModOneByte(left,right,result);
3586                 goto release ;
3587         }
3588         
3589         /* should have been converted to function call */
3590         assert(0);
3591         
3592 release :
3593         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3594         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3595         freeAsmop(result,NULL,ic,TRUE); 
3596 }
3597
3598 /*-----------------------------------------------------------------*/
3599 /* genIfxJump :- will create a jump depending on the ifx                   */
3600 /*-----------------------------------------------------------------*/
3601 /*
3602 note: May need to add parameter to indicate when a variable is in bit space.
3603 */
3604 static void genIfxJump (iCode *ic, char *jval)
3605 {
3606         
3607         FENTRY;
3608         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3609         /* if true label then we jump if condition
3610         supplied is true */
3611         if ( IC_TRUE(ic) ) {
3612                 
3613                 if(strcmp(jval,"a") == 0)
3614                         emitSKPZ;
3615                 else if (strcmp(jval,"c") == 0)
3616                         emitSKPC;
3617                 else {
3618                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3619                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3620                 }
3621                 
3622                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3623                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3624                 
3625         }
3626         else {
3627                 /* false label is present */
3628                 if(strcmp(jval,"a") == 0)
3629                         emitSKPNZ;
3630                 else if (strcmp(jval,"c") == 0)
3631                         emitSKPNC;
3632                 else {
3633                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3634                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3635                 }
3636                 
3637                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3638                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3639                 
3640         }
3641         
3642         
3643         /* mark the icode as generated */
3644         ic->generated = 1;
3645 }
3646
3647 /*-----------------------------------------------------------------*/
3648 /* genSkip                                                                                                                 */
3649 /*-----------------------------------------------------------------*/
3650 static void genSkip(iCode *ifx,int status_bit)
3651 {
3652         FENTRY;
3653         if(!ifx)
3654                 return;
3655         
3656         if ( IC_TRUE(ifx) ) {
3657                 switch(status_bit) {
3658                 case 'z':
3659                         emitSKPNZ;
3660                         break;
3661                         
3662                 case 'c':
3663                         emitSKPNC;
3664                         break;
3665                         
3666                 case 'd':
3667                         emitSKPDC;
3668                         break;
3669                         
3670                 }
3671                 
3672                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3673                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3674                 
3675         } else {
3676                 
3677                 switch(status_bit) {
3678                         
3679                 case 'z':
3680                         emitSKPZ;
3681                         break;
3682                         
3683                 case 'c':
3684                         emitSKPC;
3685                         break;
3686                         
3687                 case 'd':
3688                         emitSKPDC;
3689                         break;
3690                 }
3691                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3692                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3693                 
3694         }
3695         
3696 }
3697
3698 /*-----------------------------------------------------------------*/
3699 /* genSkipc                                                                                                        */
3700 /*-----------------------------------------------------------------*/
3701 static void genSkipc(resolvedIfx *rifx)
3702 {
3703         FENTRY;
3704         if(!rifx)
3705                 return;
3706         
3707         if(rifx->condition)
3708                 emitSKPNC;
3709         else
3710                 emitSKPC;
3711         
3712         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3713         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3714         rifx->generated = 1;
3715 }
3716
3717 /*-----------------------------------------------------------------*/
3718 /* genSkipz2                                                                                                       */
3719 /*-----------------------------------------------------------------*/
3720 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3721 {
3722         FENTRY;
3723         if(!rifx)
3724                 return;
3725         
3726         if( (rifx->condition ^ invert_condition) & 1)
3727                 emitSKPZ;
3728         else
3729                 emitSKPNZ;
3730         
3731         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3732         rifx->generated = 1;
3733 }
3734
3735 /*-----------------------------------------------------------------*/
3736 /* genSkipz                                                        */
3737 /*-----------------------------------------------------------------*/
3738 static void genSkipz(iCode *ifx, int condition)
3739 {
3740         FENTRY;
3741         if(!ifx)
3742                 return;
3743         
3744         if(condition)
3745                 emitSKPNZ;
3746         else
3747                 emitSKPZ;
3748         
3749         if ( IC_TRUE(ifx) )
3750                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3751         else
3752                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3753         
3754         if ( IC_TRUE(ifx) )
3755                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3756         else
3757                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3758         
3759 }
3760
3761 #if 0
3762 /*-----------------------------------------------------------------*/
3763 /* genSkipCond                                                     */
3764 /*-----------------------------------------------------------------*/
3765 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3766 {
3767         FENTRY;
3768         if(!rifx)
3769                 return;
3770         
3771         if(rifx->condition)
3772                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3773         else
3774                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3775         
3776         
3777         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3778         rifx->generated = 1;
3779 }
3780 #endif
3781
3782 #if 0
3783 /*-----------------------------------------------------------------*/
3784 /* genChkZeroes :- greater or less than comparison                 */
3785 /*     For each byte in a literal that is zero, inclusive or the   */
3786 /*     the corresponding byte in the operand with W                */
3787 /*     returns true if any of the bytes are zero                   */
3788 /*-----------------------------------------------------------------*/
3789 static int genChkZeroes(operand *op, int lit,  int size)
3790 {
3791         
3792         int i;
3793         int flag =1;
3794         
3795         while(size--) {
3796                 i = (lit >> (size*8)) & 0xff;
3797                 
3798                 if(i==0) {
3799                         if(flag) 
3800                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3801                         else
3802                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3803                         flag = 0;
3804                 }
3805         }
3806         
3807         return (flag==0);
3808 }
3809 #endif
3810
3811
3812 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3813 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3814 #define DEBUGpc           emitpComment
3815
3816 /*-----------------------------------------------------------------*/
3817 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3818 /*                  aop (if it's NOT a literal) or from lit (if    */
3819 /*                  aop is a literal)                              */
3820 /*-----------------------------------------------------------------*/
3821 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3822   if (aop->type == AOP_LIT) {
3823     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3824   } else {
3825     emitpcode (POC_MOVFW, popGet (aop, offset));
3826   }
3827 }
3828
3829 /* genCmp performs a left < right comparison, stores
3830  * the outcome in result (if != NULL) and generates
3831  * control flow code for the ifx (if != NULL).
3832  *
3833  * This version leaves in sequences like
3834  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3835  * which should be optmized by the peephole
3836  * optimizer - RN 2005-01-01 */
3837 static void genCmp (operand *left,operand *right,
3838                     operand *result, iCode *ifx, int sign)
3839 {
3840   resolvedIfx rIfx;
3841   int size;
3842   int offs;
3843   symbol *templbl;
3844   operand *dummy;
3845   unsigned long lit;
3846   unsigned long mask;
3847   int performedLt;
3848   int invert_result = 0;
3849
3850   FENTRY;
3851   
3852   assert (AOP_SIZE(left) == AOP_SIZE(right));
3853   assert (left && right);
3854
3855   size = AOP_SIZE(right) - 1;
3856   mask = (0x100UL << (size*8)) - 1;
3857   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3858   performedLt = 1;
3859   templbl = NULL;
3860   lit = 0;
3861   
3862   resolveIfx (&rIfx, ifx);
3863
3864   /**********************************************************************
3865    * handle bits - bit compares are promoted to int compares seemingly! *
3866    **********************************************************************/
3867 #if 0
3868   // THIS IS COMPLETELY UNTESTED!
3869   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3870     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3871     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3872     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3873
3874     emitSETC;
3875     // 1 < {0,1} is false --> clear C by skipping the next instruction
3876     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3877     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3878     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3879     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3880     emitCLRC; // only skipped for left=0 && right=1
3881
3882     goto correct_result_in_carry;
3883   } // if
3884 #endif
3885
3886   /*************************************************
3887    * make sure that left is register (or the like) *
3888    *************************************************/
3889   if (!isAOP_REGlike(left)) {
3890     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3891     assert (isAOP_LIT(left));
3892     assert (isAOP_REGlike(right));
3893     // swap left and right
3894     // left < right <==> right > left <==> (right >= left + 1)
3895     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3896
3897     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3898       // MAXVALUE < right? always false
3899       if (performedLt) emitCLRC; else emitSETC;
3900       goto correct_result_in_carry;
3901     } // if
3902
3903     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3904     // that's why we handled it above.
3905     lit++;
3906
3907     dummy = left;
3908     left = right;
3909     right = dummy;
3910
3911     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3912   } else if (isAOP_LIT(right)) {
3913     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3914   } // if
3915
3916   assert (isAOP_REGlike(left)); // left must be register or the like
3917   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3918
3919   /*************************************************
3920    * special cases go here                         *
3921    *************************************************/
3922
3923   if (isAOP_LIT(right)) {
3924     if (!sign) {
3925       // unsigned comparison to a literal
3926       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3927       if (lit == 0) {
3928         // unsigned left < 0? always false
3929         if (performedLt) emitCLRC; else emitSETC;
3930         goto correct_result_in_carry;
3931       }
3932     } else {
3933       // signed comparison to a literal
3934       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3935       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3936         // signed left < 0x80000000? always false
3937         if (performedLt) emitCLRC; else emitSETC;
3938         goto correct_result_in_carry;
3939       } else if (lit == 0) {
3940         // compare left < 0; set CARRY if SIGNBIT(left) is set
3941         if (performedLt) emitSETC; else emitCLRC;
3942         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3943         if (performedLt) emitCLRC; else emitSETC;
3944         goto correct_result_in_carry;
3945       }
3946     } // if (!sign)
3947   } // right is literal
3948
3949   /*************************************************
3950    * perform a general case comparison             *
3951    * make sure we get CARRY==1 <==> left >= right  *
3952    *************************************************/
3953   // compare most significant bytes
3954   //DEBUGpc ("comparing bytes at offset %d", size);
3955   if (!sign) {
3956     // unsigned comparison
3957     pic14_mov2w_regOrLit (AOP(right), lit, size);
3958     emitpcode (POC_SUBFW, popGet (AOP(left), size));
3959   } else {
3960     // signed comparison
3961     // (add 2^n to both operands then perform an unsigned comparison)
3962     if (isAOP_LIT(right)) {
3963       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3964       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3965
3966       if (litbyte == 0x80) {
3967         // left >= 0x80 -- always true, but more bytes to come
3968         mov2w (AOP(left), size);
3969         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3970         emitSETC;
3971       } else {
3972         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3973         mov2w (AOP(left), size);
3974         emitpcode (POC_ADDLW, popGetLit (0x80));
3975         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3976       } // if
3977     } else {
3978       pCodeOp *pctemp = popGetTempReg();
3979       mov2w (AOP(left), size);
3980       emitpcode (POC_ADDLW, popGetLit (0x80));
3981       emitpcode (POC_MOVWF, pctemp);
3982       mov2w (AOP(right), size);
3983       emitpcode (POC_ADDLW, popGetLit (0x80));
3984       emitpcode (POC_SUBFW, pctemp);
3985       popReleaseTempReg(pctemp);
3986     }
3987   } // if (!sign)
3988
3989   // compare remaining bytes (treat as unsigned case from above)
3990   templbl = newiTempLabel ( NULL );
3991   offs = size;
3992   while (offs--) {
3993     //DEBUGpc ("comparing bytes at offset %d", offs);
3994     emitSKPZ;
3995     emitpcode (POC_GOTO, popGetLabel (templbl->key));
3996     pic14_mov2w_regOrLit (AOP(right), lit, offs);
3997     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
3998   } // while (offs)
3999   emitpLabel (templbl->key);
4000   goto result_in_carry;
4001
4002 result_in_carry:
4003   
4004   /****************************************************
4005    * now CARRY contains the result of the comparison: *
4006    * SUBWF sets CARRY iff                             *
4007    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4008    * (F=left, W=right)                                *
4009    ****************************************************/
4010
4011   if (performedLt) {
4012     invert_result = 1;
4013     // value will be used in the following genSkipc()
4014     rIfx.condition ^= 1;
4015   } // if
4016
4017 correct_result_in_carry:
4018
4019   // assign result to variable (if neccessary)
4020   if (result && AOP_TYPE(result) != AOP_CRY) {
4021     //DEBUGpc ("assign result");
4022     size = AOP_SIZE(result);
4023     while (size--) {
4024       emitpcode (POC_CLRF, popGet (AOP(result), size));
4025     } // while
4026     if (invert_result) {
4027       emitSKPC;
4028       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4029     } else {
4030       emitpcode (POC_RLF, popGet (AOP(result), 0));
4031     }
4032   } // if (result)
4033
4034   // perform conditional jump
4035   if (ifx) {
4036     //DEBUGpc ("generate control flow");
4037     genSkipc (&rIfx);
4038     ifx->generated = 1;
4039   } // if
4040 }
4041
4042
4043 #if 0
4044 /* OLD VERSION -- BUGGY, DO NOT USE */
4045
4046 /*-----------------------------------------------------------------*/
4047 /* genCmp :- greater or less than comparison                       */
4048 /*-----------------------------------------------------------------*/
4049 static void genCmp (operand *left,operand *right,
4050                                         operand *result, iCode *ifx, int sign)
4051 {
4052         int size; //, offset = 0 ;
4053         unsigned long lit = 0L,i = 0;
4054         resolvedIfx rFalseIfx;
4055         //  resolvedIfx rTrueIfx;
4056         symbol *truelbl;
4057
4058         FENTRY;
4059         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4060         /*
4061         if(ifx) {
4062         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4063         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4064         }
4065         */
4066         
4067         resolveIfx(&rFalseIfx,ifx);
4068         truelbl  = newiTempLabel(NULL);
4069         size = max(AOP_SIZE(left),AOP_SIZE(right));
4070         
4071         DEBUGpic14_AopType(__LINE__,left,right,result);
4072         
4073 #define _swapp
4074         
4075         /* if literal is on the right then swap with left */
4076         if ((AOP_TYPE(right) == AOP_LIT)) {
4077                 operand *tmp = right ;
4078                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4079                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4080 #ifdef _swapp
4081                 
4082                 lit = (lit - 1) & mask;
4083                 right = left;
4084                 left = tmp;
4085                 rFalseIfx.condition ^= 1;
4086 #endif
4087                 
4088         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4089                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4090         }
4091         
4092         
4093         //if(IC_TRUE(ifx) == NULL)
4094         /* if left & right are bit variables */
4095         if (AOP_TYPE(left) == AOP_CRY &&
4096                 AOP_TYPE(right) == AOP_CRY ) {
4097                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4098                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4099         } else {
4100         /* subtract right from left if at the
4101         end the carry flag is set then we know that
4102                 left is greater than right */
4103                 
4104                 symbol *lbl  = newiTempLabel(NULL);
4105                 
4106 #ifndef _swapp
4107                 if(AOP_TYPE(right) == AOP_LIT) {
4108                         
4109                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4110                         
4111                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4112                         
4113                         /* special cases */
4114                         
4115                         if(lit == 0) {
4116                                 
4117                                 if(sign != 0) 
4118                                         genSkipCond(&rFalseIfx,left,size-1,7);
4119                                 else 
4120                                         /* no need to compare to 0...*/
4121                                         /* NOTE: this is a de-generate compare that most certainly 
4122                                         *       creates some dead code. */
4123                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4124                                 
4125                                 if(ifx) ifx->generated = 1;
4126                                 return;
4127                                 
4128                         }
4129                         size--;
4130                         
4131                         if(size == 0) {
4132                                 //i = (lit >> (size*8)) & 0xff;
4133                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4134                                 
4135                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4136                                 
4137                                 i = ((0-lit) & 0xff);
4138                                 if(sign) {
4139                                         if( i == 0x81) { 
4140                                         /* lit is 0x7f, all signed chars are less than
4141                                                 * this except for 0x7f itself */
4142                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4143                                                 genSkipz2(&rFalseIfx,0);
4144                                         } else {
4145                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4146                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4147                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4148                                         }
4149                                         
4150                                 } else {
4151                                         if(lit == 1) {
4152                                                 genSkipz2(&rFalseIfx,1);
4153                                         } else {
4154                                                 emitpcode(POC_ADDLW, popGetLit(i));
4155                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4156                                         }
4157                                 }
4158                                 
4159                                 if(ifx) ifx->generated = 1;
4160                                 return;
4161                         }
4162                         
4163                         /* chars are out of the way. now do ints and longs */
4164                         
4165                         
4166                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4167                         
4168                         /* special cases */
4169                         
4170                         if(sign) {
4171                                 
4172                                 if(lit == 0) {
4173                                         genSkipCond(&rFalseIfx,left,size,7);
4174                                         if(ifx) ifx->generated = 1;
4175                                         return;
4176                                 }
4177                                 
4178                                 if(lit <0x100) {
4179                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4180                                         
4181                                         //rFalseIfx.condition ^= 1;
4182                                         //genSkipCond(&rFalseIfx,left,size,7);
4183                                         //rFalseIfx.condition ^= 1;
4184                                         
4185                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4186                                         if(rFalseIfx.condition)
4187                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4188                                         else
4189                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4190                                         
4191                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4192                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4193                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4194                                         
4195                                         while(size > 1)
4196                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4197                                         
4198                                         if(rFalseIfx.condition) {
4199                                                 emitSKPZ;
4200                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4201                                                 
4202                                         } else {
4203                                                 emitSKPNZ;
4204                                         }
4205                                         
4206                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4207                                         emitpLabel(truelbl->key);
4208                                         if(ifx) ifx->generated = 1;
4209                                         return;
4210                                         
4211                                 }
4212                                 
4213                                 if(size == 1) {
4214                                         
4215                                         if( (lit & 0xff) == 0) {
4216                                                 /* lower byte is zero */
4217                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4218                                                 i = ((lit >> 8) & 0xff) ^0x80;
4219                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4220                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4221                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4222                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4223                                                 
4224                                                 
4225                                                 if(ifx) ifx->generated = 1;
4226                                                 return;
4227                                                 
4228                                         }
4229                                 } else {
4230                                         /* Special cases for signed longs */
4231                                         if( (lit & 0xffffff) == 0) {
4232                                                 /* lower byte is zero */
4233                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4234                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4235                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4236                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4237                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4238                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4239                                                 
4240                                                 
4241                                                 if(ifx) ifx->generated = 1;
4242                                                 return;
4243                                                 
4244                                         }
4245                                         
4246                                 }
4247                                 
4248                                 
4249                                 if(lit & (0x80 << (size*8))) {
4250                                         /* lit is negative */
4251                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4252                                         
4253                                         //genSkipCond(&rFalseIfx,left,size,7);
4254                                         
4255                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4256                                         
4257                                         if(rFalseIfx.condition)
4258                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4259                                         else
4260                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4261                                         
4262                                         
4263                                 } else {
4264                                         /* lit is positive */
4265                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4266                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4267                                         if(rFalseIfx.condition)
4268                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4269                                         else
4270                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4271                                         
4272                                 }
4273                                 
4274                                 /* There are no more special cases, so perform a general compare */
4275                                 
4276                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4277                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4278                                 
4279                                 while(size--) {
4280                                         
4281                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4282                                         emitSKPNZ;
4283                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4284                                 }
4285                                 //rFalseIfx.condition ^= 1;
4286                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4287                                 
4288                                 emitpLabel(truelbl->key);
4289                                 
4290                                 if(ifx) ifx->generated = 1;
4291                                 return;
4292                                 
4293                                 
4294                         }
4295
4296
4297                         /* sign is out of the way. So now do an unsigned compare */
4298                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4299
4300
4301                         /* General case - compare to an unsigned literal on the right.*/
4302
4303                         i = (lit >> (size*8)) & 0xff;
4304                         emitpcode(POC_MOVLW, popGetLit(i));
4305                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4306                         while(size--) {
4307                                 i = (lit >> (size*8)) & 0xff;
4308                                 
4309                                 if(i) {
4310                                         emitpcode(POC_MOVLW, popGetLit(i));
4311                                         emitSKPNZ;
4312                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4313                                 } else {
4314                                 /* this byte of the lit is zero, 
4315                                         *if it's not the last then OR in the variable */
4316                                         if(size)
4317                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4318                                 }
4319                         }
4320
4321
4322                 emitpLabel(lbl->key);
4323                 //if(emitFinalCheck)
4324                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4325                 if(sign)
4326                         emitpLabel(truelbl->key);
4327
4328                 if(ifx) ifx->generated = 1;
4329                 return;
4330
4331
4332                 }
4333 #endif  // _swapp
4334
4335                 if(AOP_TYPE(left) == AOP_LIT) {
4336                         //symbol *lbl = newiTempLabel(NULL);
4337                         
4338                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4339                         
4340                         
4341                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4342                         
4343                         /* Special cases */
4344                         if((lit == 0) && (sign == 0)){
4345                                 
4346                                 size--;
4347                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4348                                 while(size) 
4349                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4350                                 
4351                                 genSkipz2(&rFalseIfx,0);
4352                                 if(ifx) ifx->generated = 1;
4353                                 return;
4354                         }
4355                         
4356                         if(size==1) {
4357                                 /* Special cases */
4358                                 lit &= 0xff;
4359                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4360                                         /* degenerate compare can never be true */
4361                                         if(rFalseIfx.condition == 0)
4362                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4363                                         
4364                                         if(ifx) ifx->generated = 1;
4365                                         return;
4366                                 }
4367                                 
4368                                 if(sign) {
4369                                         /* signed comparisons to a literal byte */
4370                                         
4371                                         int lp1 = (lit+1) & 0xff;
4372                                         
4373                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4374                                         switch (lp1) {
4375                                         case 0:
4376                                                 rFalseIfx.condition ^= 1;
4377                                                 genSkipCond(&rFalseIfx,right,0,7);
4378                                                 break;
4379                                         case 0x7f:
4380                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4381                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4382                                                 genSkipz2(&rFalseIfx,1);
4383                                                 break;
4384                                         default:
4385                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4386                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4387                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4388                                                 rFalseIfx.condition ^= 1;
4389                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4390                                                 break;
4391                                         }
4392                                         if(ifx) ifx->generated = 1;
4393                                 } else {
4394                                         /* unsigned comparisons to a literal byte */
4395                                         
4396                                         switch(lit & 0xff ) {
4397                                         case 0:
4398                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4399                                                 genSkipz2(&rFalseIfx,0);
4400                                                 if(ifx) ifx->generated = 1;
4401                                                 break;
4402                                         case 0x7f:
4403                                                 genSkipCond(&rFalseIfx,right,0,7);
4404                                                 if(ifx) ifx->generated = 1;
4405                                                 break;
4406                                                 
4407                                         default:
4408                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4409                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4410                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4411                                                 rFalseIfx.condition ^= 1;
4412                                                 if (AOP_TYPE(result) == AOP_CRY) {
4413                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4414                                                         if(ifx) ifx->generated = 1;
4415                                                 } else {
4416                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4417                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4418                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4419                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4420                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4421                                                 }       
4422                                                 break;
4423                                         }
4424                                 }
4425                                 
4426                                 //goto check_carry;
4427                                 return;
4428                                 
4429                         } else {
4430                                 
4431                                 /* Size is greater than 1 */
4432                                 
4433                                 if(sign) {
4434                                         int lp1 = lit+1;
4435                                         
4436                                         size--;
4437                                         
4438                                         if(lp1 == 0) {
4439                                                 /* this means lit = 0xffffffff, or -1 */
4440                                                 
4441                                                 
4442                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4443                                                 rFalseIfx.condition ^= 1;
4444                                                 genSkipCond(&rFalseIfx,right,size,7);
4445                                                 if(ifx) ifx->generated = 1;
4446                                                 return;
4447                                         }
4448                                         
4449                                         if(lit == 0) {
4450                                                 int s = size;
4451                                                 
4452                                                 if(rFalseIfx.condition) {
4453                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4454                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4455                                                 }
4456                                                 
4457                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4458                                                 while(size--)
4459                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4460                                                 
4461                                                 
4462                                                 emitSKPZ;
4463                                                 if(rFalseIfx.condition) {
4464                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4465                                                         emitpLabel(truelbl->key);
4466                                                 }else {
4467                                                         rFalseIfx.condition ^= 1;
4468                                                         genSkipCond(&rFalseIfx,right,s,7);
4469                                                 }
4470                                                 
4471                                                 if(ifx) ifx->generated = 1;
4472                                                 return;
4473                                         }
4474                                         
4475                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4476                                                 /* lower byte of signed word is zero */
4477                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4478                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4479                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4480                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4481                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4482                                                 rFalseIfx.condition ^= 1;
4483                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4484                                                 
4485                                                 
4486                                                 if(ifx) ifx->generated = 1;
4487                                                 return;
4488                                         }
4489                                         
4490                                         if(lit & (0x80 << (size*8))) {
4491                                                 /* Lit is less than zero */
4492                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4493                                                 //rFalseIfx.condition ^= 1;
4494                                                 //genSkipCond(&rFalseIfx,left,size,7);
4495                                                 //rFalseIfx.condition ^= 1;
4496                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4497                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4498                                                 
4499                                                 if(rFalseIfx.condition)
4500                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4501                                                 else
4502                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4503                                                 
4504                                                 
4505                                         } else {
4506                                                 /* Lit is greater than or equal to zero */
4507                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4508                                                 //rFalseIfx.condition ^= 1;
4509                                                 //genSkipCond(&rFalseIfx,right,size,7);
4510                                                 //rFalseIfx.condition ^= 1;
4511                                                 
4512                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4513                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4514                                                 
4515                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4516                                                 if(rFalseIfx.condition)
4517                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4518                                                 else
4519                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4520                                                 
4521                                         }
4522                                         
4523                                         
4524                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4525                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4526                                         
4527                                         while(size--) {
4528                                                 
4529                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4530                                                 emitSKPNZ;
4531                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4532                                         }
4533                                         rFalseIfx.condition ^= 1;
4534                                         //rFalseIfx.condition = 1;
4535                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4536                                         
4537                                         emitpLabel(truelbl->key);
4538                                         
4539                                         if(ifx) ifx->generated = 1;
4540                                         return;
4541                                         // end of if (sign)
4542                                 } else {
4543                                         
4544                                         /* compare word or long to an unsigned literal on the right.*/
4545                                         
4546                                         
4547                                         size--;
4548                                         if(lit < 0xff) {
4549                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4550                                                 switch (lit) {
4551                                                 case 0:
4552                                                         break; /* handled above */
4553                                                 /*
4554                                                 case 0xff:
4555                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4556                                                         while(size--)
4557                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4558                                                         genSkipz2(&rFalseIfx,0);
4559                                                         break;
4560                                                 */
4561                                                 default:
4562                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4563                                                         while(--size)
4564                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4565                                                         
4566                                                         emitSKPZ;
4567                                                         if(rFalseIfx.condition)
4568                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4569                                                         else
4570                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4571                                                         
4572                                                         
4573                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4574                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4575                                                         
4576                                                         rFalseIfx.condition ^= 1;
4577                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4578                                                 }
4579                                                 
4580                                                 emitpLabel(truelbl->key);
4581                                                 
4582                                                 if(ifx) ifx->generated = 1;
4583                                                 return;
4584                                         }
4585                                         
4586                                         
4587                                         lit++;
4588                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4589                                         i = (lit >> (size*8)) & 0xff;
4590                                         
4591                                         emitpcode(POC_MOVLW, popGetLit(i));
4592                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4593                                         
4594                                         while(size--) {
4595                                                 i = (lit >> (size*8)) & 0xff;
4596                                                 
4597                                                 if(i) {
4598                                                         emitpcode(POC_MOVLW, popGetLit(i));
4599                                                         emitSKPNZ;
4600                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4601                                                 } else {
4602                                                 /* this byte of the lit is zero, 
4603                                                         *if it's not the last then OR in the variable */
4604                                                         if(size)
4605                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4606                                                 }
4607                                         }
4608                                         
4609                                         
4610                                         emitpLabel(lbl->key);
4611                                         
4612                                         rFalseIfx.condition ^= 1;
4613                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4614                                 }
4615                                 
4616                                 if(sign)
4617                                         emitpLabel(truelbl->key);
4618                                 if(ifx) ifx->generated = 1;
4619                                 return;
4620                         }
4621                 }
4622                 /* Compare two variables */
4623                 
4624                 DEBUGpic14_emitcode(";sign","%d",sign);
4625                 
4626                 size--;
4627                 if(sign) {
4628                         /* Sigh. thus sucks... */
4629                         if(size) {
4630                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4631                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4632                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4633                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4634                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4635                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4636                         } else {
4637                                 /* Signed char comparison */
4638                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4639                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4640                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4641                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4642                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4643                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4644                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4645                                 
4646                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4647                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4648                                 
4649                                 if(ifx) ifx->generated = 1;
4650                                 return;
4651                         }
4652                         
4653                 } else {
4654                         
4655                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4656                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4657                 }
4658                 
4659                 
4660                 /* The rest of the bytes of a multi-byte compare */
4661                 while (size) {
4662                         
4663                         emitSKPZ;
4664                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4665                         size--;
4666                         
4667                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4668                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4669                         
4670                         
4671                 }
4672                 
4673                 emitpLabel(lbl->key);
4674                 
4675                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4676                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4677                         (AOP_TYPE(result) == AOP_REG)) {
4678                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4679                         emitpcode(POC_RLF, popGet(AOP(result),0));
4680                 } else {
4681                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4682                 }       
4683                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4684                 if(ifx) ifx->generated = 1;
4685                 
4686                 return;
4687                 
4688         }
4689         
4690         // check_carry:
4691         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4692                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4693                 pic14_outBitC(result);
4694         } else {
4695                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4696                 /* if the result is used in the next
4697                 ifx conditional branch then generate
4698                 code a little differently */
4699                 if (ifx )
4700                         genIfxJump (ifx,"c");
4701                 else
4702                         pic14_outBitC(result);
4703                 /* leave the result in acc */
4704         }
4705         
4706 }
4707 #endif
4708
4709 /*-----------------------------------------------------------------*/
4710 /* genCmpGt :- greater than comparison                             */
4711 /*-----------------------------------------------------------------*/
4712 static void genCmpGt (iCode *ic, iCode *ifx)
4713 {
4714         operand *left, *right, *result;
4715         sym_link *letype , *retype;
4716         int sign ;
4717         
4718         FENTRY;
4719         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4720         left = IC_LEFT(ic);
4721         right= IC_RIGHT(ic);
4722         result = IC_RESULT(ic);
4723         
4724         letype = getSpec(operandType(left));
4725         retype =getSpec(operandType(right));
4726         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4727         /* assign the amsops */
4728         aopOp (left,ic,FALSE);
4729         aopOp (right,ic,FALSE);
4730         aopOp (result,ic,TRUE);
4731         
4732         genCmp(right, left, result, ifx, sign);
4733         
4734         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4735         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4736         freeAsmop(result,NULL,ic,TRUE); 
4737 }
4738
4739 /*-----------------------------------------------------------------*/
4740 /* genCmpLt - less than comparisons                                */
4741 /*-----------------------------------------------------------------*/
4742 static void genCmpLt (iCode *ic, iCode *ifx)
4743 {
4744         operand *left, *right, *result;
4745         sym_link *letype , *retype;
4746         int sign ;
4747         
4748         FENTRY;
4749         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4750         left = IC_LEFT(ic);
4751         right= IC_RIGHT(ic);
4752         result = IC_RESULT(ic);
4753         
4754         letype = getSpec(operandType(left));
4755         retype =getSpec(operandType(right));
4756         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4757         
4758         /* assign the amsops */
4759         aopOp (left,ic,FALSE);
4760         aopOp (right,ic,FALSE);
4761         aopOp (result,ic,TRUE);
4762         
4763         genCmp(left, right, result, ifx, sign);
4764         
4765         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4766         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4767         freeAsmop(result,NULL,ic,TRUE); 
4768 }
4769
4770 /*-----------------------------------------------------------------*/
4771 /* genc16bit2lit - compare a 16 bit value to a literal             */
4772 /*-----------------------------------------------------------------*/
4773 static void genc16bit2lit(operand *op, int lit, int offset)
4774 {
4775         int i;
4776         
4777         FENTRY;
4778         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4779         if( (lit&0xff) == 0) 
4780                 i=1;
4781         else
4782                 i=0;
4783         
4784         switch( BYTEofLONG(lit,i)) { 
4785         case 0:
4786                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4787                 break;
4788         case 1:
4789                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4790                 break;
4791         case 0xff:
4792                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4793                 break;
4794         default:
4795                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4796                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4797         }
4798         
4799         i ^= 1;
4800         
4801         switch( BYTEofLONG(lit,i)) { 
4802         case 0:
4803                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4804                 break;
4805         case 1:
4806                 emitSKPNZ;
4807                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4808                 break;
4809         case 0xff:
4810                 emitSKPNZ;
4811                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4812                 break;
4813         default:
4814                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4815                 emitSKPNZ;
4816                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4817                 
4818         }
4819         
4820 }
4821
4822 /*-----------------------------------------------------------------*/
4823 /* gencjneshort - compare and jump if not equal                    */
4824 /*-----------------------------------------------------------------*/
4825 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4826 {
4827         int size = max(AOP_SIZE(left),AOP_SIZE(right));
4828         int offset = 0;
4829         int res_offset = 0;  /* the result may be a different size then left or right */
4830         int res_size = AOP_SIZE(result);
4831         resolvedIfx rIfx;
4832         symbol *lbl;
4833         
4834         unsigned long lit = 0L;
4835         FENTRY;
4836         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4837           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4838           return;
4839         }
4840         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4841         DEBUGpic14_AopType(__LINE__,left,right,result);
4842         if(result)
4843                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4844         resolveIfx(&rIfx,ifx);
4845         lbl =  newiTempLabel(NULL);
4846         
4847         
4848         /* if the left side is a literal or 
4849         if the right is in a pointer register and left 
4850         is not */
4851         if ((AOP_TYPE(left) == AOP_LIT) || 
4852                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4853                 operand *t = right;
4854                 right = left;
4855                 left = t;
4856         }
4857         if(AOP_TYPE(right) == AOP_LIT)
4858                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4859         
4860         /* if the right side is a literal then anything goes */
4861         if (AOP_TYPE(right) == AOP_LIT &&
4862                 AOP_TYPE(left) != AOP_DIR ) {
4863                 switch(size) {
4864                 case 2:
4865                         genc16bit2lit(left, lit, 0);
4866                         emitSKPNZ;
4867                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4868                         break;
4869                 default:
4870                         while (size--) {
4871                                 if(lit & 0xff) {
4872                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4873                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4874                                 } else {
4875                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4876                                 }
4877                                 
4878                                 emitSKPNZ;
4879                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4880                                 offset++;
4881                                 if(res_offset < res_size-1)
4882                                         res_offset++;
4883                                 lit >>= 8;
4884                         }
4885                         break;
4886                 }
4887         }
4888         
4889         /* if the right side is in a register or in direct space or
4890         if the left is a pointer register & right is not */    
4891         else if (AOP_TYPE(right) == AOP_REG ||
4892                 AOP_TYPE(right) == AOP_DIR || 
4893                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4894                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4895                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4896                 int lbl_key = lbl->key;
4897                 
4898                 if(result) {
4899                         if (AOP_TYPE(result) != AOP_CRY)
4900                                 emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
4901                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4902                 }else {
4903                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4904                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4905                                 __FUNCTION__,__LINE__);
4906                         return;
4907                 }
4908                 
4909                 /*     switch(size) { */
4910                 /*     case 2: */
4911                 /*       genc16bit2lit(left, lit, 0); */
4912                 /*       emitSKPNZ; */
4913                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4914                 /*       break; */
4915                 /*     default: */
4916                 while (size--) {
4917                         int emit_skip=1;
4918                         if((AOP_TYPE(left) == AOP_DIR) && 
4919                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4920                                 
4921                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4922                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4923                                 
4924                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4925                                 
4926                                 switch (lit & 0xff) {
4927                                 case 0:
4928                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4929                                         break;
4930                                 case 1:
4931                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4932                                         emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4933                                         //emitpcode(POC_GOTO,popGetLabel(lbl->key));
4934                                         emit_skip=0;
4935                                         break;
4936                                 case 0xff:
4937                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4938                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4939                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4940                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4941                                         emit_skip=0;
4942                                         break;
4943                                 default:
4944                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4945                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4946                                 }
4947                                 lit >>= 8;
4948                                 
4949                         } else {
4950                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4951                         }
4952                         if(emit_skip) {
4953                                 if(AOP_TYPE(result) == AOP_CRY) {
4954                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4955                                         if(rIfx.condition)
4956                                                 emitSKPNZ;
4957                                         else
4958                                                 emitSKPZ;
4959                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4960                                 } else {
4961                                         /* fix me. probably need to check result size too */
4962                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
4963                                         if(rIfx.condition)
4964                                                 emitSKPZ;
4965                                         else
4966                                                 emitSKPNZ;
4967                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4968                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4969                                 }
4970                                 if(ifx)
4971                                         ifx->generated=1;
4972                         }
4973                         emit_skip++;
4974                         offset++;
4975                         if(res_offset < res_size-1)
4976                                 res_offset++;
4977                 }
4978                 /*       break; */
4979                 /*     } */
4980         } else if(AOP_TYPE(right) == AOP_REG &&
4981                 AOP_TYPE(left) != AOP_DIR){
4982                 
4983                 while(size--) {
4984                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4985                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
4986                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4987                         if(rIfx.condition)
4988                                 emitSKPNZ;
4989                         else
4990                                 emitSKPZ;
4991                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4992                         offset++;
4993                         if(res_offset < res_size-1)
4994                                 res_offset++;
4995                 }
4996                 
4997         }else{
4998                 /* right is a pointer reg need both a & b */
4999                 while(size--) {
5000                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5001                         if(strcmp(l,"b"))
5002                                 pic14_emitcode("mov","b,%s",l);
5003                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5004                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5005                         offset++;
5006                 }
5007         }
5008         
5009         emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5010         if(!rIfx.condition)
5011                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5012         
5013         emitpLabel(lbl->key);
5014         
5015         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5016         
5017         if(ifx)
5018                 ifx->generated = 1;
5019 }
5020
5021 #if 0
5022 /*-----------------------------------------------------------------*/
5023 /* gencjne - compare and jump if not equal                         */
5024 /*-----------------------------------------------------------------*/
5025 static void gencjne(operand *left, operand *right, iCode *ifx)
5026 {
5027         symbol *tlbl  = newiTempLabel(NULL);
5028         
5029         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5030         gencjneshort(left, right, lbl);
5031         
5032         pic14_emitcode("mov","a,%s",one);
5033         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5034         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5035         pic14_emitcode("clr","a");
5036         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5037         
5038         emitpLabel(lbl->key);
5039         emitpLabel(tlbl->key);
5040         
5041 }
5042 #endif
5043
5044 /*-----------------------------------------------------------------*/
5045 /* genCmpEq - generates code for equal to                          */
5046 /*-----------------------------------------------------------------*/
5047 static void genCmpEq (iCode *ic, iCode *ifx)
5048 {
5049         operand *left, *right, *result;
5050         unsigned long lit = 0L;
5051         int size,offset=0;
5052         
5053         FENTRY;
5054         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5055         
5056         if(ifx)
5057                 DEBUGpic14_emitcode ("; ifx is non-null","");
5058         else
5059                 DEBUGpic14_emitcode ("; ifx is null","");
5060         
5061         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5062         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5063         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5064         
5065         size = max(AOP_SIZE(left),AOP_SIZE(right));
5066         
5067         DEBUGpic14_AopType(__LINE__,left,right,result);
5068         
5069         /* if literal, literal on the right or 
5070         if the right is in a pointer register and left 
5071         is not */
5072         if (aop_isLitLike (AOP(IC_LEFT(ic)))
5073                         || (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5074                 operand *tmp = right ;
5075                 right = left;
5076                 left = tmp;
5077         }
5078         
5079         
5080         if(ifx && !AOP_SIZE(result)){
5081                 symbol *tlbl;
5082                 /* if they are both bit variables */
5083                 if (AOP_TYPE(left) == AOP_CRY &&
5084                         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5085                         if(AOP_TYPE(right) == AOP_LIT){
5086                                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5087                                 if(lit == 0L){
5088                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5089                                         pic14_emitcode("cpl","c");
5090                                 } else if(lit == 1L) {
5091                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5092                                 } else {
5093                                         pic14_emitcode("clr","c");
5094                                 }
5095                                 /* AOP_TYPE(right) == AOP_CRY */
5096                         } else {
5097                                 symbol *lbl = newiTempLabel(NULL);
5098                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5099                                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5100                                 pic14_emitcode("cpl","c");
5101                                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5102                         }
5103                         /* if true label then we jump if condition
5104                         supplied is true */
5105                         tlbl = newiTempLabel(NULL);
5106                         if ( IC_TRUE(ifx) ) {
5107                                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
5108                                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5109                         } else {
5110                                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
5111                                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5112                         }
5113                         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5114                         
5115                         {
5116                                 /* left and right are both bit variables, result is carry */
5117                                 resolvedIfx rIfx;
5118                                 
5119                                 resolveIfx(&rIfx,ifx);
5120                                 
5121                                 emitpcode(POC_MOVLW,popGet(AOP(left),0));
5122                                 emitpcode(POC_ANDFW,popGet(AOP(left),0));
5123                                 emitpcode(POC_BTFSC,popGet(AOP(right),0));
5124                                 emitpcode(POC_ANDLW,popGet(AOP(left),0));
5125                                 genSkipz2(&rIfx,0);
5126                         }
5127                 } else {
5128                         
5129                         /* They're not both bit variables. Is the right a literal? */
5130                         if(AOP_TYPE(right) == AOP_LIT) {
5131                                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5132                                 
5133                                 switch(size) {
5134                                         
5135                                 case 1:
5136                                         switch(lit & 0xff) {
5137                                         case 1:
5138                                                 if ( IC_TRUE(ifx) ) {
5139                                                         emitpcode(POC_DECFW,popGet(AOP(left),offset));
5140                                                         emitSKPNZ;
5141                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5142                                                 } else {
5143                                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5144                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5145                                                 }
5146                                                 break;
5147                                         case 0xff:
5148                                                 if ( IC_TRUE(ifx) ) {
5149                                                         emitpcode(POC_INCFW,popGet(AOP(left),offset));
5150                                                         emitSKPNZ;
5151                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5152                                                 } else {
5153                                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5154                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5155                                                 }
5156                                                 break;
5157                                         default:
5158                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5159                                                 if(lit)
5160                                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5161                                                 genSkip(ifx,'z');
5162                                         }
5163                                         
5164                                         
5165                                         /* end of size == 1 */
5166                                         break;
5167                                         
5168                                         case 2:
5169                                                 genc16bit2lit(left,lit,offset);
5170                                                 genSkip(ifx,'z');
5171                                                 break;
5172                                                 /* end of size == 2 */
5173                                                 
5174                                         default:
5175                                                 /* size is 4 */
5176                                                 if(lit==0) {
5177                                                         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5178                                                         emitpcode(POC_IORFW,popGet(AOP(left),1));
5179                                                         emitpcode(POC_IORFW,popGet(AOP(left),2));
5180                                                         emitpcode(POC_IORFW,popGet(AOP(left),3));
5181                                                         
5182                                                 } else {
5183                                                         
5184                                                         /* search for patterns that can be optimized */
5185                                                         
5186                                                         genc16bit2lit(left,lit,0);
5187                                                         lit >>= 16;
5188                                                         if(lit) {
5189                                                                 genSkipz(ifx,IC_TRUE(ifx) == NULL);
5190                                                                 //genSkip(ifx,'z');
5191                                                                 genc16bit2lit(left,lit,2);
5192                                                         } else {
5193                                                                 emitpcode(POC_IORFW,popGet(AOP(left),2));
5194                                                                 emitpcode(POC_IORFW,popGet(AOP(left),3));
5195                                                                 
5196                                                         }
5197                                                         
5198                                                 }
5199                                                 
5200                                                 genSkip(ifx,'z');
5201                                 }
5202                                 
5203                                 ifx->generated = 1;
5204                                 goto release ;
5205                                 
5206                                 
5207                         } else if(AOP_TYPE(right) == AOP_CRY ) {
5208                                 /* we know the left is not a bit, but that the right is */
5209                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5210                                 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5211                                         popGet(AOP(right),offset));
5212                                 emitpcode(POC_XORLW,popGetLit(1));
5213                                 
5214                                 /* if the two are equal, then W will be 0 and the Z bit is set
5215                                 * we could test Z now, or go ahead and check the high order bytes if
5216                                 * the variable we're comparing is larger than a byte. */
5217                                 
5218                                 while(--size)
5219                                         emitpcode(POC_IORFW,popGet(AOP(left),offset));
5220                                 
5221                                 if ( IC_TRUE(ifx) ) {
5222                                         emitSKPNZ;
5223                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5224                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5225                                 } else {
5226                                         emitSKPZ;
5227                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5228                                         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5229                                 }
5230                                 
5231                         } else {
5232                                 /* They're both variables that are larger than bits */
5233                                 int s = size;
5234                                 
5235                                 tlbl = newiTempLabel(NULL);
5236                                 
5237                                 while(size--) {
5238                                         mov2w (AOP(right),offset); /* right might be litLike() */
5239                                         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5240                                         
5241                                         if ( IC_TRUE(ifx) ) {
5242                                                 if(size) {
5243                                                         emitSKPZ;
5244                                                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5245                                                         pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5246                                                 } else {
5247                                                         emitSKPNZ;
5248                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5249                                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5250                                                 }
5251                                         } else {
5252                                                 emitSKPZ;
5253                                                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5254                                                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5255                                         }
5256                                         offset++;
5257                                 }
5258                                 if(s>1 && IC_TRUE(ifx)) {
5259                                         emitpLabel(tlbl->key);
5260                                         pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5261                                 }
5262                         }
5263                 }
5264                 /* mark the icode as generated */
5265                 ifx->generated = 1;
5266                 goto release ;
5267         }
5268   
5269   /* if they are both bit variables */
5270   if (AOP_TYPE(left) == AOP_CRY &&
5271           ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5272           if(AOP_TYPE(right) == AOP_LIT){
5273                   unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5274                   if(lit == 0L){
5275                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5276                           pic14_emitcode("cpl","c");
5277                   } else if(lit == 1L) {
5278                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5279                   } else {
5280                           pic14_emitcode("clr","c");
5281                   }
5282                   /* AOP_TYPE(right) == AOP_CRY */
5283           } else {
5284                   symbol *lbl = newiTempLabel(NULL);
5285                   pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5286                   pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5287                   pic14_emitcode("cpl","c");
5288                   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5289           }
5290           /* c = 1 if egal */
5291           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5292                   pic14_outBitC(result);
5293                   goto release ;
5294           }
5295           if (ifx) {
5296                   genIfxJump (ifx,"c");
5297                   goto release ;
5298           }
5299           /* if the result is used in an arithmetic operation
5300           then put the result in place */
5301           pic14_outBitC(result);
5302   } else {
5303           
5304           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5305           gencjne(left,right,result,ifx);
5306           /*
5307           if(ifx) 
5308           gencjne(left,right,newiTempLabel(NULL));
5309           else {
5310           if(IC_TRUE(ifx)->key)
5311           gencjne(left,right,IC_TRUE(ifx)->key);
5312           else
5313           gencjne(left,right,IC_FALSE(ifx)->key);
5314           ifx->generated = 1;
5315           goto release ;
5316           }
5317           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5318           aopPut(AOP(result),"a",0);
5319           goto release ;
5320           }
5321           
5322                 if (ifx) {
5323                 genIfxJump (ifx,"a");
5324                 goto release ;
5325                 }
5326           */
5327           /* if the result is used in an arithmetic operation
5328           then put the result in place */
5329           /*
5330           if (AOP_TYPE(result) != AOP_CRY) 
5331           pic14_outAcc(result);
5332           */
5333           /* leave the result in acc */
5334   }
5335   
5336 release:
5337   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5338   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5339   freeAsmop(result,NULL,ic,TRUE);
5340 }
5341
5342 /*-----------------------------------------------------------------*/
5343 /* ifxForOp - returns the icode containing the ifx for operand     */
5344 /*-----------------------------------------------------------------*/
5345 static iCode *ifxForOp ( operand *op, iCode *ic )
5346 {
5347         FENTRY;
5348         /* if true symbol then needs to be assigned */
5349         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5350         if (IS_TRUE_SYMOP(op))
5351                 return NULL ;
5352         
5353         /* if this has register type condition and
5354         the next instruction is ifx with the same operand
5355         and live to of the operand is upto the ifx only then */
5356         if (ic->next &&
5357                 ic->next->op == IFX &&
5358                 IC_COND(ic->next)->key == op->key &&
5359                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5360                 return ic->next;
5361         
5362         if (ic->next &&
5363                 ic->next->op == IFX &&
5364                 IC_COND(ic->next)->key == op->key) {
5365                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5366                 return ic->next;
5367         }
5368         
5369         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5370         if (ic->next &&
5371                 ic->next->op == IFX)
5372                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5373         
5374         if (ic->next &&
5375                 ic->next->op == IFX &&
5376                 IC_COND(ic->next)->key == op->key) {
5377                 DEBUGpic14_emitcode ("; "," key is okay");
5378                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5379                         OP_SYMBOL(op)->liveTo,
5380                         ic->next->seq);
5381         }
5382         
5383         
5384         return NULL;
5385 }
5386 /*-----------------------------------------------------------------*/
5387 /* genAndOp - for && operation                                     */
5388 /*-----------------------------------------------------------------*/
5389 static void genAndOp (iCode *ic)
5390 {
5391         operand *left,*right, *result;
5392         /*     symbol *tlbl; */
5393         
5394         FENTRY;
5395         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5396         /* note here that && operations that are in an
5397         if statement are taken away by backPatchLabels
5398         only those used in arthmetic operations remain */
5399         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5400         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5401         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5402         
5403         DEBUGpic14_AopType(__LINE__,left,right,result);
5404         
5405         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5406         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5407         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5408         
5409         /* if both are bit variables */
5410         /*     if (AOP_TYPE(left) == AOP_CRY && */
5411         /*         AOP_TYPE(right) == AOP_CRY ) { */
5412         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5413         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5414         /*         pic14_outBitC(result); */
5415         /*     } else { */
5416         /*         tlbl = newiTempLabel(NULL); */
5417         /*         pic14_toBoolean(left);     */
5418         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5419         /*         pic14_toBoolean(right); */
5420         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5421         /*         pic14_outBitAcc(result); */
5422         /*     } */
5423         
5424         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5425         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5426         freeAsmop(result,NULL,ic,TRUE);
5427 }
5428
5429
5430 /*-----------------------------------------------------------------*/
5431 /* genOrOp - for || operation                                      */
5432 /*-----------------------------------------------------------------*/
5433 /*
5434 tsd pic port -
5435 modified this code, but it doesn't appear to ever get called
5436 */
5437
5438 static void genOrOp (iCode *ic)
5439 {
5440         operand *left,*right, *result;
5441         symbol *tlbl;
5442         
5443         /* note here that || operations that are in an
5444         if statement are taken away by backPatchLabels
5445         only those used in arthmetic operations remain */
5446         FENTRY;
5447         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5448         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5449         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5450         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5451         
5452         DEBUGpic14_AopType(__LINE__,left,right,result);
5453         
5454         /* if both are bit variables */
5455         if (AOP_TYPE(left) == AOP_CRY &&
5456                 AOP_TYPE(right) == AOP_CRY ) {
5457                 pic14_emitcode("clrc","");
5458                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5459                         AOP(left)->aopu.aop_dir,
5460                         AOP(left)->aopu.aop_dir);
5461                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5462                         AOP(right)->aopu.aop_dir,
5463                         AOP(right)->aopu.aop_dir);
5464                 pic14_emitcode("setc","");
5465                 
5466         } else {
5467                 tlbl = newiTempLabel(NULL);
5468                 pic14_toBoolean(left);
5469                 emitSKPZ;
5470                 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5471                 pic14_toBoolean(right);
5472                 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5473                 
5474                 pic14_outBitAcc(result);
5475         }
5476         
5477         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5478         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5479         freeAsmop(result,NULL,ic,TRUE);            
5480 }
5481
5482 /*-----------------------------------------------------------------*/
5483 /* isLiteralBit - test if lit == 2^n                               */
5484 /*-----------------------------------------------------------------*/
5485 static int isLiteralBit(unsigned long lit)
5486 {
5487         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5488                 0x100L,0x200L,0x400L,0x800L,
5489                 0x1000L,0x2000L,0x4000L,0x8000L,
5490                 0x10000L,0x20000L,0x40000L,0x80000L,
5491                 0x100000L,0x200000L,0x400000L,0x800000L,
5492                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5493                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5494         int idx;
5495         
5496         FENTRY;
5497         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5498         for(idx = 0; idx < 32; idx++)
5499                 if(lit == pw[idx])
5500                         return idx+1;
5501                 return 0;
5502 }
5503
5504 /*-----------------------------------------------------------------*/
5505 /* continueIfTrue -                                                */
5506 /*-----------------------------------------------------------------*/
5507 static void continueIfTrue (iCode *ic)
5508 {
5509         FENTRY;
5510         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5511         if(IC_TRUE(ic))
5512                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5513         ic->generated = 1;
5514 }
5515
5516 /*-----------------------------------------------------------------*/
5517 /* jmpIfTrue -                                                     */
5518 /*-----------------------------------------------------------------*/
5519 static void jumpIfTrue (iCode *ic)
5520 {
5521         FENTRY;
5522         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5523         if(!IC_TRUE(ic))
5524                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5525         ic->generated = 1;
5526 }
5527
5528 /*-----------------------------------------------------------------*/
5529 /* jmpTrueOrFalse -                                                */
5530 /*-----------------------------------------------------------------*/
5531 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5532 {
5533         FENTRY;
5534         // ugly but optimized by peephole
5535         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5536         if(IC_TRUE(ic)){
5537                 symbol *nlbl = newiTempLabel(NULL);
5538                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5539                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5540                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5541                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5542         }
5543         else{
5544                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5545                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5546         }
5547         ic->generated = 1;
5548 }
5549
5550 /*-----------------------------------------------------------------*/
5551 /* genAnd  - code for and                                          */
5552 /*-----------------------------------------------------------------*/
5553 static void genAnd (iCode *ic, iCode *ifx)
5554 {
5555         operand *left, *right, *result;
5556         int size, offset=0;  
5557         unsigned long lit = 0L;
5558         int bytelit = 0;
5559         resolvedIfx rIfx;
5560         
5561         FENTRY;
5562         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5563         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5564         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5565         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5566         
5567         resolveIfx(&rIfx,ifx);
5568         
5569         /* if left is a literal & right is not then exchange them */
5570         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5571                 AOP_NEEDSACC(left)) {
5572                 operand *tmp = right ;
5573                 right = left;
5574                 left = tmp;
5575         }
5576         
5577         /* if result = right then exchange them */
5578         if(pic14_sameRegs(AOP(result),AOP(right))){
5579                 operand *tmp = right ;
5580                 right = left;
5581                 left = tmp;
5582         }
5583         
5584         /* if right is bit then exchange them */
5585         if (AOP_TYPE(right) == AOP_CRY &&
5586                 AOP_TYPE(left) != AOP_CRY){
5587                 operand *tmp = right ;
5588                 right = left;
5589                 left = tmp;
5590         }
5591         if(AOP_TYPE(right) == AOP_LIT)
5592                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5593         
5594         size = AOP_SIZE(result);
5595         
5596         DEBUGpic14_AopType(__LINE__,left,right,result);
5597         
5598         // if(bit & yy)
5599         // result = bit & yy;
5600         if (AOP_TYPE(left) == AOP_CRY){
5601                 // c = bit & literal;
5602                 if(AOP_TYPE(right) == AOP_LIT){
5603                         if(lit & 1) {
5604                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5605                                         // no change
5606                                         goto release;
5607                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5608                         } else {
5609                                 // bit(result) = 0;
5610                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5611                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5612                                         goto release;
5613                                 }
5614                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5615                                         jumpIfTrue(ifx);
5616                                         goto release;
5617                                 }
5618                                 pic14_emitcode("clr","c");
5619                         }
5620                 } else {
5621                         if (AOP_TYPE(right) == AOP_CRY){
5622                                 // c = bit & bit;
5623                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5624                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5625                         } else {
5626                                 // c = bit & val;
5627                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5628                                 // c = lsb
5629                                 pic14_emitcode("rrc","a");
5630                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5631                         }
5632                 }
5633                 // bit = c
5634                 // val = c
5635                 if(size)
5636                         pic14_outBitC(result);
5637                 // if(bit & ...)
5638                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5639                         genIfxJump(ifx, "c");           
5640                 goto release ;
5641         }
5642         
5643         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5644         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5645         if((AOP_TYPE(right) == AOP_LIT) &&
5646                 (AOP_TYPE(result) == AOP_CRY) &&
5647                 (AOP_TYPE(left) != AOP_CRY)){
5648                 int posbit = isLiteralBit(lit);
5649                 /* left &  2^n */
5650                 if(posbit){
5651                         posbit--;
5652                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5653                         // bit = left & 2^n
5654                         if(size)
5655                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5656                         // if(left &  2^n)
5657                         else{
5658                                 if(ifx){
5659                                         int offset = 0;
5660                                         while (posbit > 7) {
5661                                                 posbit -= 8;
5662                                                 offset++;
5663                                         }
5664                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5665                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5666                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5667                                         
5668                                         ifx->generated = 1;
5669                                 }
5670                                 goto release;
5671                         }
5672                 } else {
5673                         symbol *tlbl = newiTempLabel(NULL);
5674                         int sizel = AOP_SIZE(left);
5675                         if(size)
5676                                 pic14_emitcode("setb","c");
5677                         while(sizel--){
5678                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5679                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5680                                         // byte ==  2^n ?
5681                                         if((posbit = isLiteralBit(bytelit)) != 0)
5682                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5683                                         else{
5684                                                 if(bytelit != 0x0FFL)
5685                                                         pic14_emitcode("anl","a,%s",
5686                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5687                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5688                                         }
5689                                 }
5690                                 offset++;
5691                         }
5692                         // bit = left & literal
5693                         if(size){
5694                                 pic14_emitcode("clr","c");
5695                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5696                         }
5697                         // if(left & literal)
5698                         else{
5699                                 if(ifx)
5700                                         jmpTrueOrFalse(ifx, tlbl);
5701                                 goto release ;
5702                         }
5703                 }
5704                 pic14_outBitC(result);
5705                 goto release ;
5706         }
5707         
5708         /* if left is same as result */
5709         if(pic14_sameRegs(AOP(result),AOP(left))){
5710                 int know_W = -1;
5711                 for(;size--; offset++,lit>>=8) {
5712                         if(AOP_TYPE(right) == AOP_LIT){
5713                                 switch(lit & 0xff) {
5714                                 case 0x00:
5715                                         /*  and'ing with 0 has clears the result */
5716                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5717                                         break;
5718                                 case 0xff:
5719                                         /* and'ing with 0xff is a nop when the result and left are the same */
5720                                         break;
5721                                         
5722                                 default:
5723                                         {
5724                                                 int p = my_powof2( (~lit) & 0xff );
5725                                                 if(p>=0) {
5726                                                         /* only one bit is set in the literal, so use a bcf instruction */
5727                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5728                                                         
5729                                                 } else {
5730                                                         if(know_W != (int)(lit&0xff))
5731                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5732                                                         know_W = lit &0xff;
5733                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5734                                                 }
5735                                         }    
5736                                 }
5737                         } else {
5738                                 if (AOP_TYPE(left) == AOP_ACC) {
5739                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5740                                 } else {        
5741                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5742                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5743                                         
5744                                 }
5745                         }
5746                 }
5747                 
5748         } else {
5749                 // left & result in different registers
5750                 if(AOP_TYPE(result) == AOP_CRY){
5751                         // result = bit
5752                         // if(size), result in bit
5753                         // if(!size && ifx), conditional oper: if(left & right)
5754                         symbol *tlbl = newiTempLabel(NULL);
5755                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5756                         if(size)
5757                                 pic14_emitcode("setb","c");
5758                         while(sizer--){
5759                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5760                                 pic14_emitcode("anl","a,%s",
5761                                         aopGet(AOP(left),offset,FALSE,FALSE));
5762                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5763                                 offset++;
5764                         }
5765                         if(size){
5766                                 CLRC;
5767                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5768                                 pic14_outBitC(result);
5769                         } else if(ifx)
5770                                 jmpTrueOrFalse(ifx, tlbl);
5771                 } else {
5772                         for(;(size--);offset++) {
5773                                 // normal case
5774                                 // result = left & right
5775                                 if(AOP_TYPE(right) == AOP_LIT){
5776                                         int t = (lit >> (offset*8)) & 0x0FFL;
5777                                         switch(t) { 
5778                                         case 0x00:
5779                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5780                                                 break;
5781                                         case 0xff:
5782                                                 if(AOP_TYPE(left) != AOP_ACC) {
5783                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5784                                                 }
5785                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5786                                                 break;
5787                                         default:
5788                                                 if(AOP_TYPE(left) == AOP_ACC) {
5789                                                         emitpcode(POC_ANDLW, popGetLit(t));
5790                                                 } else {
5791                                                         emitpcode(POC_MOVLW, popGetLit(t));
5792                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5793                                                 }
5794                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5795                                         }
5796                                         continue;
5797                                 }
5798                                 
5799                                 if (AOP_TYPE(left) == AOP_ACC) {
5800                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5801                                 } else {
5802                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5803                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5804                                 }
5805                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5806                         }
5807                 }
5808         }
5809         
5810 release :
5811         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5812         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5813         freeAsmop(result,NULL,ic,TRUE);     
5814 }
5815
5816 /*-----------------------------------------------------------------*/
5817 /* genOr  - code for or                                            */
5818 /*-----------------------------------------------------------------*/
5819 static void genOr (iCode *ic, iCode *ifx)
5820 {
5821         operand *left, *right, *result;
5822         int size, offset=0;
5823         unsigned long lit = 0L;
5824         
5825         FENTRY;
5826         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5827         
5828         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5829         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5830         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5831         
5832         DEBUGpic14_AopType(__LINE__,left,right,result);
5833         
5834         /* if left is a literal & right is not then exchange them */
5835         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5836                 AOP_NEEDSACC(left)) {
5837                 operand *tmp = right ;
5838                 right = left;
5839                 left = tmp;
5840         }
5841         
5842         /* if result = right then exchange them */
5843         if(pic14_sameRegs(AOP(result),AOP(right))){
5844                 operand *tmp = right ;
5845                 right = left;
5846                 left = tmp;
5847         }
5848         
5849         /* if right is bit then exchange them */
5850         if (AOP_TYPE(right) == AOP_CRY &&
5851                 AOP_TYPE(left) != AOP_CRY){
5852                 operand *tmp = right ;
5853                 right = left;
5854                 left = tmp;
5855         }
5856         
5857         DEBUGpic14_AopType(__LINE__,left,right,result);
5858         
5859         if(AOP_TYPE(right) == AOP_LIT)
5860                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5861         
5862         size = AOP_SIZE(result);
5863         
5864         // if(bit | yy)
5865         // xx = bit | yy;
5866         if (AOP_TYPE(left) == AOP_CRY){
5867                 if(AOP_TYPE(right) == AOP_LIT){
5868                         // c = bit & literal;
5869                         if(lit){
5870                                 // lit != 0 => result = 1
5871                                 if(AOP_TYPE(result) == AOP_CRY){
5872                                         if(size)
5873                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5874                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5875                                         //   AOP(result)->aopu.aop_dir,
5876                                         //   AOP(result)->aopu.aop_dir);
5877                                         else if(ifx)
5878                                                 continueIfTrue(ifx);
5879                                         goto release;
5880                                 }
5881                         } else {
5882                                 // lit == 0 => result = left
5883                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5884                                         goto release;
5885                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5886                         }
5887                 } else {
5888                         if (AOP_TYPE(right) == AOP_CRY){
5889                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5890                                         // c = bit | bit;
5891                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5892                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5893                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5894                                         
5895                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5896                                                 AOP(result)->aopu.aop_dir,
5897                                                 AOP(result)->aopu.aop_dir);
5898                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5899                                                 AOP(right)->aopu.aop_dir,
5900                                                 AOP(right)->aopu.aop_dir);
5901                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5902                                                 AOP(result)->aopu.aop_dir,
5903                                                 AOP(result)->aopu.aop_dir);
5904                                 } else {
5905                                         if( AOP_TYPE(result) == AOP_ACC) {
5906                                                 emitpcode(POC_MOVLW, popGetLit(0));
5907                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5908                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5909                                                 emitpcode(POC_MOVLW, popGetLit(1));
5910                                                 
5911                                         } else {
5912                                                 
5913                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5914                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5915                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5916                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5917                                                 
5918                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5919                                                         AOP(result)->aopu.aop_dir,
5920                                                         AOP(result)->aopu.aop_dir);
5921                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5922                                                         AOP(right)->aopu.aop_dir,
5923                                                         AOP(right)->aopu.aop_dir);
5924                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5925                                                         AOP(left)->aopu.aop_dir,
5926                                                         AOP(left)->aopu.aop_dir);
5927                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5928                                                         AOP(result)->aopu.aop_dir,
5929                                                         AOP(result)->aopu.aop_dir);
5930                                         }
5931                                 }
5932                         } else {
5933                                 // c = bit | val;
5934                                 symbol *tlbl = newiTempLabel(NULL);
5935                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5936                                 
5937                                 
5938                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5939                                 if( AOP_TYPE(right) == AOP_ACC) {
5940                                         emitpcode(POC_IORLW, popGetLit(0));
5941                                         emitSKPNZ;
5942                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5943                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5944                                 }
5945                                 
5946                                 
5947                                 
5948                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5949                                         pic14_emitcode(";XXX setb","c");
5950                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5951                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5952                                 pic14_toBoolean(right);
5953                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5954                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5955                                         jmpTrueOrFalse(ifx, tlbl);
5956                                         goto release;
5957                                 } else {
5958                                         CLRC;
5959                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5960                                 }
5961                         }
5962                 }
5963                 // bit = c
5964                 // val = c
5965                 if(size)
5966                         pic14_outBitC(result);
5967                 // if(bit | ...)
5968                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5969                         genIfxJump(ifx, "c");           
5970                 goto release ;
5971         }
5972
5973         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5974         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5975         if((AOP_TYPE(right) == AOP_LIT) &&
5976           (AOP_TYPE(result) == AOP_CRY) &&
5977           (AOP_TYPE(left) != AOP_CRY)){
5978                 if(lit){
5979                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5980                         // result = 1
5981                         if(size)
5982                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5983                         else 
5984                                 continueIfTrue(ifx);
5985                         goto release;
5986                 } else {
5987                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5988                         // lit = 0, result = boolean(left)
5989                         if(size)
5990                                 pic14_emitcode(";XXX setb","c");
5991                         pic14_toBoolean(right);
5992                         if(size){
5993                                 symbol *tlbl = newiTempLabel(NULL);
5994                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5995                                 CLRC;
5996                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5997                         } else {
5998                                 genIfxJump (ifx,"a");
5999                                 goto release;
6000                         }
6001                 }
6002                 pic14_outBitC(result);
6003                 goto release ;
6004         }
6005
6006         /* if left is same as result */
6007         if(pic14_sameRegs(AOP(result),AOP(left))){
6008                 int know_W = -1;
6009                 for(;size--; offset++,lit>>=8) {
6010                         if(AOP_TYPE(right) == AOP_LIT){
6011                                 if((lit & 0xff) == 0)
6012                                         /*  or'ing with 0 has no effect */
6013                                         continue;
6014                                 else {
6015                                         int p = my_powof2(lit & 0xff);
6016                                         if(p>=0) {
6017                                                 /* only one bit is set in the literal, so use a bsf instruction */
6018                                                 emitpcode(POC_BSF,
6019                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6020                                         } else {
6021                                                 if(know_W != (int)(lit & 0xff))
6022                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6023                                                 know_W = lit & 0xff;
6024                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6025                                         }
6026                                         
6027                                 }
6028                         } else {
6029                                 if (AOP_TYPE(left) == AOP_ACC) {
6030                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
6031                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6032                                 } else {        
6033                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
6034                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
6035                                         
6036                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6037                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6038                                         
6039                                 }
6040                         }
6041                 }
6042         } else {
6043                 // left & result in different registers
6044                 if(AOP_TYPE(result) == AOP_CRY){
6045                         // result = bit
6046                         // if(size), result in bit
6047                         // if(!size && ifx), conditional oper: if(left | right)
6048                         symbol *tlbl = newiTempLabel(NULL);
6049                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6050                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6051                         
6052                         
6053                         if(size)
6054                                 pic14_emitcode(";XXX setb","c");
6055                         while(sizer--){
6056                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6057                                 pic14_emitcode(";XXX orl","a,%s",
6058                                         aopGet(AOP(left),offset,FALSE,FALSE));
6059                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6060                                 offset++;
6061                         }
6062                         if(size){
6063                                 CLRC;
6064                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6065                                 pic14_outBitC(result);
6066                         } else if(ifx)
6067                                 jmpTrueOrFalse(ifx, tlbl);
6068                 } else for(;(size--);offset++){
6069                         // normal case
6070                         // result = left | right
6071                         if(AOP_TYPE(right) == AOP_LIT){
6072                                 int t = (lit >> (offset*8)) & 0x0FFL;
6073                                 switch(t) { 
6074                                 case 0x00:
6075                                         if (AOP_TYPE(left) != AOP_ACC) {
6076                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6077                                         }
6078                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6079                                         
6080                                         break;
6081                                 default:
6082                                         if (AOP_TYPE(left) == AOP_ACC) {
6083                                                 emitpcode(POC_IORLW,  popGetLit(t));
6084                                         } else {
6085                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6086                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6087                                         }
6088                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6089                                 }
6090                                 continue;
6091                         }
6092                         
6093                         // faster than result <- left, anl result,right
6094                         // and better if result is SFR
6095                         if (AOP_TYPE(left) == AOP_ACC) {
6096                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6097                         } else {
6098                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6099                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6100                         }
6101                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6102                 }
6103         }
6104
6105 release :
6106         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6107         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6108         freeAsmop(result,NULL,ic,TRUE);     
6109 }
6110
6111 /*-----------------------------------------------------------------*/
6112 /* genXor - code for xclusive or                                   */
6113 /*-----------------------------------------------------------------*/
6114 static void genXor (iCode *ic, iCode *ifx)
6115 {
6116         operand *left, *right, *result;
6117         int size, offset=0;
6118         unsigned long lit = 0L;
6119         
6120         FENTRY;
6121         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6122         
6123         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6124         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6125         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6126         
6127         /* if left is a literal & right is not ||
6128         if left needs acc & right does not */
6129         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6130                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6131                 operand *tmp = right ;
6132                 right = left;
6133                 left = tmp;
6134         }
6135         
6136         /* if result = right then exchange them */
6137         if(pic14_sameRegs(AOP(result),AOP(right))){
6138                 operand *tmp = right ;
6139                 right = left;
6140                 left = tmp;
6141         }
6142         
6143         /* if right is bit then exchange them */
6144         if (AOP_TYPE(right) == AOP_CRY &&
6145                 AOP_TYPE(left) != AOP_CRY){
6146                 operand *tmp = right ;
6147                 right = left;
6148                 left = tmp;
6149         }
6150         if(AOP_TYPE(right) == AOP_LIT)
6151                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6152         
6153         size = AOP_SIZE(result);
6154         
6155         // if(bit ^ yy)
6156         // xx = bit ^ yy;
6157         if (AOP_TYPE(left) == AOP_CRY){
6158                 if(AOP_TYPE(right) == AOP_LIT){
6159                         // c = bit & literal;
6160                         if(lit>>1){
6161                                 // lit>>1  != 0 => result = 1
6162                                 if(AOP_TYPE(result) == AOP_CRY){
6163                                         if(size)
6164                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6165                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6166                                         else if(ifx)
6167                                                 continueIfTrue(ifx);
6168                                         goto release;
6169                                 }
6170                                 pic14_emitcode("setb","c");
6171                         } else{
6172                                 // lit == (0 or 1)
6173                                 if(lit == 0){
6174                                         // lit == 0, result = left
6175                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6176                                                 goto release;
6177                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6178                                 } else{
6179                                         // lit == 1, result = not(left)
6180                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6181                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6182                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6183                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6184                                                 goto release;
6185                                         } else {
6186                                                 assert ( !"incomplete genXor" );
6187                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6188                                                 pic14_emitcode("cpl","c");
6189                                         }
6190                                 }
6191                         }
6192                         
6193                 } else {
6194                         // right != literal
6195                         symbol *tlbl = newiTempLabel(NULL);
6196                         if (AOP_TYPE(right) == AOP_CRY){
6197                                 // c = bit ^ bit;
6198                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6199                         }
6200                         else{
6201                                 int sizer = AOP_SIZE(right);
6202                                 // c = bit ^ val
6203                                 // if val>>1 != 0, result = 1
6204                                 pic14_emitcode("setb","c");
6205                                 while(sizer){
6206                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6207                                         if(sizer == 1)
6208                                                 // test the msb of the lsb
6209                                                 pic14_emitcode("anl","a,#0xfe");
6210                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6211                                         sizer--;
6212                                 }
6213                                 // val = (0,1)
6214                                 pic14_emitcode("rrc","a");
6215                         }
6216                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6217                         pic14_emitcode("cpl","c");
6218                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6219                 }
6220                 // bit = c
6221                 // val = c
6222                 if(size)
6223                         pic14_outBitC(result);
6224                 // if(bit | ...)
6225                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6226                         genIfxJump(ifx, "c");           
6227                 goto release ;
6228         }
6229         
6230         if(pic14_sameRegs(AOP(result),AOP(left))){
6231                 /* if left is same as result */
6232                 for(;size--; offset++) {
6233                         if(AOP_TYPE(right) == AOP_LIT){
6234                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6235                                 if(t == 0x00L)
6236                                         continue;
6237                                 else
6238                                         if (IS_AOP_PREG(left)) {
6239                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6240                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6241                                                 aopPut(AOP(result),"a",offset);
6242                                         } else {
6243                                                 emitpcode(POC_MOVLW, popGetLit(t));
6244                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6245                                                 pic14_emitcode("xrl","%s,%s",
6246                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6247                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6248                                         }
6249                         } else {
6250                                 if (AOP_TYPE(left) == AOP_ACC)
6251                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6252                                 else {
6253                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6254                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6255                                         /*
6256                                         if (IS_AOP_PREG(left)) {
6257                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6258                                         aopPut(AOP(result),"a",offset);
6259                                         } else
6260                                         pic14_emitcode("xrl","%s,a",
6261                                         aopGet(AOP(left),offset,FALSE,TRUE));
6262                                         */
6263                                 }
6264                         }
6265                 }
6266         } else {
6267                 // left & result in different registers
6268                 if(AOP_TYPE(result) == AOP_CRY){
6269                         // result = bit
6270                         // if(size), result in bit
6271                         // if(!size && ifx), conditional oper: if(left ^ right)
6272                         symbol *tlbl = newiTempLabel(NULL);
6273                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6274                         if(size)
6275                                 pic14_emitcode("setb","c");
6276                         while(sizer--){
6277                                 if((AOP_TYPE(right) == AOP_LIT) &&
6278                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6279                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6280                                 } else {
6281                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6282                                         pic14_emitcode("xrl","a,%s",
6283                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6284                                 }
6285                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6286                                 offset++;
6287                         }
6288                         if(size){
6289                                 CLRC;
6290                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6291                                 pic14_outBitC(result);
6292                         } else if(ifx)
6293                                 jmpTrueOrFalse(ifx, tlbl);
6294                 } else for(;(size--);offset++){
6295                         // normal case
6296                         // result = left & right
6297                         if(AOP_TYPE(right) == AOP_LIT){
6298                                 int t = (lit >> (offset*8)) & 0x0FFL;
6299                                 switch(t) { 
6300                                 case 0x00:
6301                                         if (AOP_TYPE(left) != AOP_ACC) {
6302                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6303                                         }
6304                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6305                                         pic14_emitcode("movf","%s,w",
6306                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6307                                         pic14_emitcode("movwf","%s",
6308                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6309                                         break;
6310                                 case 0xff:
6311                                         if (AOP_TYPE(left) == AOP_ACC) {
6312                                                 emitpcode(POC_XORLW, popGetLit(t));
6313                                         } else {
6314                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6315                                         }
6316                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6317                                         break;
6318                                 default:
6319                                         if (AOP_TYPE(left) == AOP_ACC) {
6320                                                 emitpcode(POC_XORLW, popGetLit(t));
6321                                         } else {
6322                                                 emitpcode(POC_MOVLW, popGetLit(t));
6323                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6324                                         }
6325                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6326                                         pic14_emitcode("movlw","0x%x",t);
6327                                         pic14_emitcode("xorwf","%s,w",
6328                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6329                                         pic14_emitcode("movwf","%s",
6330                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6331                                         
6332                                 }
6333                                 continue;
6334                         }
6335                         
6336                         // faster than result <- left, anl result,right
6337                         // and better if result is SFR
6338                         if (AOP_TYPE(left) == AOP_ACC) {
6339                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6340                         } else {
6341                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6342                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6343                         }
6344                         if ( AOP_TYPE(result) != AOP_ACC){
6345                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6346                         }
6347                 }
6348         }
6349         
6350 release :
6351         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6352         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6353         freeAsmop(result,NULL,ic,TRUE);     
6354 }
6355
6356 /*-----------------------------------------------------------------*/
6357 /* genInline - write the inline code out                           */
6358 /*-----------------------------------------------------------------*/
6359 static void genInline (iCode *ic)
6360 {
6361   char *buffer, *bp, *bp1;
6362
6363   FENTRY;
6364   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6365
6366   _G.inLine += (!options.asmpeep);
6367
6368   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6369   strcpy(buffer,IC_INLINE(ic));
6370
6371   /* emit each line as a code */
6372   while (*bp) {
6373     if (*bp == '\n') {
6374       *bp++ = '\0';
6375       
6376       if(*bp1)
6377         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6378       bp1 = bp;
6379     } else {
6380       if (*bp == ':') {
6381         bp++;
6382         *bp = '\0';
6383         bp++;
6384
6385         /* print label, use this special format with NULL directive
6386          * to denote that the argument should not be indented with tab */
6387         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6388
6389         bp1 = bp;
6390       } else
6391         bp++;
6392     }
6393   }
6394   if ((bp1 != bp) && *bp1)
6395     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6396
6397   Safe_free(buffer);
6398
6399   _G.inLine -= (!options.asmpeep);
6400 }
6401
6402 /*-----------------------------------------------------------------*/
6403 /* genRRC - rotate right with carry                                */
6404 /*-----------------------------------------------------------------*/
6405 static void genRRC (iCode *ic)
6406 {
6407         operand *left , *result ;
6408         int size, offset = 0, same;
6409         
6410         FENTRY;
6411         /* rotate right with carry */
6412         left = IC_LEFT(ic);
6413         result=IC_RESULT(ic);
6414         aopOp (left,ic,FALSE);
6415         aopOp (result,ic,FALSE);
6416         
6417         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6418         
6419         same = pic14_sameRegs(AOP(result),AOP(left));
6420         
6421         size = AOP_SIZE(result);    
6422         
6423         /* get the lsb and put it into the carry */
6424         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6425         
6426         offset = 0 ;
6427         
6428         while(size--) {
6429                 
6430                 if(same) {
6431                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6432                 } else {
6433                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6434                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6435                 }
6436                 
6437                 offset++;
6438         }
6439         
6440         freeAsmop(left,NULL,ic,TRUE);
6441         freeAsmop(result,NULL,ic,TRUE);
6442 }
6443
6444 /*-----------------------------------------------------------------*/
6445 /* genRLC - generate code for rotate left with carry               */
6446 /*-----------------------------------------------------------------*/
6447 static void genRLC (iCode *ic)
6448 {    
6449         operand *left , *result ;
6450         int size, offset = 0;
6451         int same;
6452         
6453         FENTRY;
6454         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6455         /* rotate right with carry */
6456         left = IC_LEFT(ic);
6457         result=IC_RESULT(ic);
6458         aopOp (left,ic,FALSE);
6459         aopOp (result,ic,FALSE);
6460         
6461         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6462         
6463         same = pic14_sameRegs(AOP(result),AOP(left));
6464         
6465         /* move it to the result */
6466         size = AOP_SIZE(result);    
6467         
6468         /* get the msb and put it into the carry */
6469         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6470         
6471         offset = 0 ;
6472         
6473         while(size--) {
6474                 
6475                 if(same) {
6476                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6477                 } else {
6478                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6479                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6480                 }
6481                 
6482                 offset++;
6483         }
6484         
6485         
6486         freeAsmop(left,NULL,ic,TRUE);
6487         freeAsmop(result,NULL,ic,TRUE);
6488 }
6489
6490 /*-----------------------------------------------------------------*/
6491 /* genGetHbit - generates code get highest order bit               */
6492 /*-----------------------------------------------------------------*/
6493 static void genGetHbit (iCode *ic)
6494 {
6495         operand *left, *result;
6496         left = IC_LEFT(ic);
6497         result=IC_RESULT(ic);
6498         aopOp (left,ic,FALSE);
6499         aopOp (result,ic,FALSE);
6500         
6501         FENTRY;
6502         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6503         /* get the highest order byte into a */
6504         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6505         if(AOP_TYPE(result) == AOP_CRY){
6506                 pic14_emitcode("rlc","a");
6507                 pic14_outBitC(result);
6508         }
6509         else{
6510                 pic14_emitcode("rl","a");
6511                 pic14_emitcode("anl","a,#0x01");
6512                 pic14_outAcc(result);
6513         }
6514         
6515         
6516         freeAsmop(left,NULL,ic,TRUE);
6517         freeAsmop(result,NULL,ic,TRUE);
6518 }
6519
6520 /*-----------------------------------------------------------------*/
6521 /* AccRol - rotate left accumulator by known count                 */
6522 /*-----------------------------------------------------------------*/
6523 static void AccRol (operand *op,int offset,int shCount)
6524 {
6525         FENTRY;
6526         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6527         shCount &= 0x0007;              // shCount : 0..7
6528         switch(shCount){
6529         case 0 :
6530                 break;
6531         case 1 :
6532                 pic14_emitcode("rl","a");
6533                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6534                 break;
6535         case 2 :
6536                 pic14_emitcode("rl","a");
6537                 pic14_emitcode("rl","a");
6538                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6539                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6540                 break;
6541         case 3 :
6542                 pic14_emitcode("swap","a");
6543                 pic14_emitcode("rr","a");
6544                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6545                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6546                 break;
6547         case 4 :
6548                 pic14_emitcode("swap","a");
6549                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6550                 break;
6551         case 5 :
6552                 pic14_emitcode("swap","a");
6553                 pic14_emitcode("rl","a");
6554                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6555                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6556                 break;
6557         case 6 :
6558                 pic14_emitcode("rr","a");
6559                 pic14_emitcode("rr","a");
6560                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6561                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6562                 break;
6563         case 7 :
6564                 pic14_emitcode("rr","a");
6565                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6566                 break;
6567         }
6568 }
6569
6570 /*-----------------------------------------------------------------*/
6571 /* AccLsh - left shift accumulator by known count                  */
6572 /*-----------------------------------------------------------------*/
6573 static void AccLsh (operand *op,int offset,int shCount)
6574 {
6575         FENTRY;
6576         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6577         if(shCount != 0) {
6578                 if (shCount == 1)
6579                 {
6580                         emitCLRC;
6581                         emitpcode (POC_RLF, popGet (AOP(op), 0));
6582                 } else {
6583                         /* rotate left accumulator */
6584                         AccRol(op,offset,shCount);
6585                         /* and kill the lower order bits */
6586                         emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
6587                         emitpcode (POC_ANDWF, popGet (AOP(op),0));
6588                 }
6589         }
6590 }
6591
6592 /*-----------------------------------------------------------------*/
6593 /* AccRsh - right shift accumulator by known count                 */
6594 /*-----------------------------------------------------------------*/
6595 static void AccRsh (operand *op,int offset,int shCount)
6596 {
6597         FENTRY;
6598         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6599         if(shCount != 0){
6600                 if(shCount == 1){
6601                         emitCLRC;
6602                         emitpcode (POC_RRF, popGet (AOP(op), 0));
6603                 } else {
6604                         /* rotate right accumulator */
6605                         AccRol(op,offset,8 - shCount);
6606                         /* and kill the higher order bits */
6607                         emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
6608                         emitpcode (POC_ANDWF, popGet (AOP(op),0));
6609                 }
6610         }
6611 }
6612
6613 #if 0
6614 /*-----------------------------------------------------------------*/
6615 /* AccSRsh - signed right shift accumulator by known count                 */
6616 /*-----------------------------------------------------------------*/
6617 static void AccSRsh (int shCount)
6618 {
6619         symbol *tlbl ;
6620         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6621         if(shCount != 0){
6622                 if(shCount == 1){
6623                         pic14_emitcode("mov","c,acc.7");
6624                         pic14_emitcode("rrc","a");
6625                 } else if(shCount == 2){
6626                         pic14_emitcode("mov","c,acc.7");
6627                         pic14_emitcode("rrc","a");
6628                         pic14_emitcode("mov","c,acc.7");
6629                         pic14_emitcode("rrc","a");
6630                 } else {
6631                         tlbl = newiTempLabel(NULL);
6632                         /* rotate right accumulator */
6633                         AccRol(8 - shCount);
6634                         /* and kill the higher order bits */
6635                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6636                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6637                         pic14_emitcode("orl","a,#0x%02x",
6638                                 (unsigned char)~SRMask[shCount]);
6639                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6640                 }
6641         }
6642 }
6643
6644 /*-----------------------------------------------------------------*/
6645 /* shiftR1Left2Result - shift right one byte from left to result   */
6646 /*-----------------------------------------------------------------*/
6647 static void shiftR1Left2ResultSigned (operand *left, int offl,
6648                                                                           operand *result, int offr,
6649                                                                           int shCount)
6650 {
6651         int same;
6652         
6653         FENTRY;
6654         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6655         
6656         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6657         
6658         switch(shCount) {
6659         case 1:
6660                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6661                 if(same) 
6662                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6663                 else {
6664                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6665                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6666                 }
6667                 
6668                 break;
6669         case 2:
6670                 
6671                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6672                 if(same) 
6673                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6674                 else {
6675                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6676                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6677                 }
6678                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6679                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6680                 
6681                 break;
6682                 
6683         case 3:
6684                 if(same)
6685                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6686                 else {
6687                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6688                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6689                 }
6690                 
6691                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6692                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6693                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6694                 
6695                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6696                 emitpcode(POC_IORLW, popGetLit(0xe0));
6697                 
6698                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6699                 break;
6700                 
6701         case 4:
6702                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6703                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6704                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6705                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6706                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6707                 break;
6708         case 5:
6709                 if(same) {
6710                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6711                 } else {
6712                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6713                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6714                 }
6715                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6716                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6717                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6718                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6719                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6720                 break;
6721                 
6722         case 6:
6723                 if(same) {
6724                         emitpcode(POC_MOVLW, popGetLit(0x00));
6725                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6726                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6727                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6728                         emitpcode(POC_IORLW, popGetLit(0x01));
6729                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6730                 } else {
6731                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6732                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6733                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6734                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6735                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6736                 }
6737                 break;
6738                 
6739         case 7:
6740                 if(same) {
6741                         emitpcode(POC_MOVLW, popGetLit(0x00));
6742                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6743                         emitpcode(POC_MOVLW, popGetLit(0xff));
6744                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6745                 } else {
6746                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6747                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6748                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6749                 }
6750                 
6751         default:
6752                 break;
6753         }
6754 }
6755
6756 /*-----------------------------------------------------------------*/
6757 /* shiftR1Left2Result - shift right one byte from left to result   */
6758 /*-----------------------------------------------------------------*/
6759 static void shiftR1Left2Result (operand *left, int offl,
6760                                                                 operand *result, int offr,
6761                                                                 int shCount, int sign)
6762 {
6763         int same;
6764         
6765         FENTRY;
6766         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6767         
6768         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6769         
6770         /* Copy the msb into the carry if signed. */
6771         if(sign) {
6772                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6773                 return;
6774         }
6775         
6776         
6777         
6778         switch(shCount) {
6779         case 1:
6780                 emitCLRC;
6781                 if(same) 
6782                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6783                 else {
6784                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6785                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6786                 }
6787                 break;
6788         case 2:
6789                 emitCLRC;
6790                 if(same) {
6791                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6792                 } else {
6793                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6794                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6795                 }
6796                 emitCLRC;
6797                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6798                 
6799                 break;
6800         case 3:
6801                 if(same)
6802                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6803                 else {
6804                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6805                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6806                 }
6807                 
6808                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6809                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6810                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6811                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6812                 break;
6813                 
6814         case 4:
6815                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6816                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6817                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6818                 break;
6819                 
6820         case 5:
6821                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6822                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6823                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6824                 emitCLRC;
6825                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6826                 
6827                 break;
6828         case 6:
6829                 
6830                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6831                 emitpcode(POC_ANDLW, popGetLit(0x80));
6832                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6833                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6834                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6835                 break;
6836                 
6837         case 7:
6838                 
6839                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6840                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6841                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6842                 
6843                 break;
6844                 
6845         default:
6846                 break;
6847         }
6848 }
6849
6850 /*-----------------------------------------------------------------*/
6851 /* shiftL1Left2Result - shift left one byte from left to result    */
6852 /*-----------------------------------------------------------------*/
6853 static void shiftL1Left2Result (operand *left, int offl,
6854                                                                 operand *result, int offr, int shCount)
6855 {
6856         int same;
6857         
6858         //    char *l;
6859         FENTRY;
6860         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6861         
6862         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6863         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6864         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6865         //    MOVA(l);
6866         /* shift left accumulator */
6867         //AccLsh(shCount); // don't comment out just yet...
6868         //    aopPut(AOP(result),"a",offr);
6869         
6870         switch(shCount) {
6871         case 1:
6872                 /* Shift left 1 bit position */
6873                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6874                 if(same) {
6875                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6876                 } else {
6877                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6878                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6879                 }
6880                 break;
6881         case 2:
6882                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6883                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6884                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6885                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6886                 break;
6887         case 3:
6888                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6889                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6890                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6891                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6892                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6893                 break;
6894         case 4:
6895                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6896                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6897                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6898                 break;
6899         case 5:
6900                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6901                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6902                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6903                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6904                 break;
6905         case 6:
6906                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6907                 emitpcode(POC_ANDLW, popGetLit(0x30));
6908                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6909                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6910                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6911                 break;
6912         case 7:
6913                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6914                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6915                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6916                 break;
6917                 
6918         default:
6919                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6920         }
6921         
6922 }
6923 #endif
6924
6925 /*-----------------------------------------------------------------*/
6926 /* movLeft2Result - move byte from left to result                  */
6927 /*-----------------------------------------------------------------*/
6928 static void movLeft2Result (operand *left, int offl,
6929                                                         operand *result, int offr)
6930 {
6931         char *l;
6932         FENTRY;
6933         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6934         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6935                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6936                 
6937                 if (*l == '@' && (IS_AOP_PREG(result))) {
6938                         pic14_emitcode("mov","a,%s",l);
6939                         aopPut(AOP(result),"a",offr);
6940                 } else {
6941                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6942                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6943                 }
6944         }
6945 }
6946
6947 /*-----------------------------------------------------------------*/
6948 /* shiftLeft_Left2ResultLit - shift left by known count            */
6949 /*-----------------------------------------------------------------*/
6950
6951 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6952 {
6953         int size, same, offr, i;
6954
6955         size = AOP_SIZE(left);
6956         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6957         
6958         same = pic14_sameRegs (AOP(left), AOP(result));
6959         
6960         offr = shCount / 8;
6961         shCount = shCount & 0x07;
6962
6963         size -= offr;
6964
6965         switch (shCount)
6966         {
6967         case 0: /* takes 0 or 2N cycles (for offr==0) */
6968                 if (!same || offr) {
6969                         for (i=size-1; i >= 0; i--)
6970                                 movLeft2Result (left, i, result, offr + i);
6971                 } // if
6972                 break;
6973                 
6974         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6975                 if (same && offr) {
6976                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6977                         shiftLeft_Left2ResultLit (result, result, shCount);
6978                         return; /* prevent clearing result again */
6979                 } else {
6980                         emitCLRC;
6981                         for (i=0; i < size; i++) {
6982                                 if (same && !offr) {
6983                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6984                                 } else {
6985                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6986                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6987                                 } // if
6988                         } // for
6989                 } // if (offr)
6990                 break;
6991                 
6992         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6993                 /* works in-place/with offr as well */
6994                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6995                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6996                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
6997
6998                 for (i = size - 2; i >= 0; i--)
6999                 {
7000                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7001                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7002                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7003                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7004                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7005                 } // for i
7006                 break;
7007                 
7008         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7009                 /* works in-place/with offr as well */
7010                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7011                 for (i = size-2; i >= 0; i--) {
7012                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7013                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7014                 } // for i
7015                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7016                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7017                 break;
7018         
7019         default:
7020                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7021                 shiftLeft_Left2ResultLit (result, result, 1);
7022                 return; /* prevent clearing result again */
7023                 break;
7024         } // switch
7025
7026         while (0 < offr--)
7027         {
7028                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7029         } // while
7030 }
7031
7032 /*-----------------------------------------------------------------*/
7033 /* shiftRight_Left2ResultLit - shift right by known count          */
7034 /*-----------------------------------------------------------------*/
7035
7036 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7037 {
7038         int size, same, offr, i;
7039
7040         size = AOP_SIZE(left);
7041         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7042         
7043         same = pic14_sameRegs (AOP(left), AOP(result));
7044         
7045         offr = shCount / 8;
7046         shCount = shCount & 0x07;
7047
7048         size -= offr;
7049
7050         if (size)
7051         {
7052                 switch (shCount)
7053                 {
7054                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7055                         if (!same || offr) {
7056                                 for (i=0; i < size; i++)
7057                                         movLeft2Result (left, i + offr, result, i);
7058                         } // if
7059                         break;
7060                         
7061                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7062                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7063                         if (same && offr) {
7064                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7065                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7066                                 return; /* prevent sign-extending result again */
7067                         } else {
7068                                 emitCLRC;
7069                                 if (sign) {
7070                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7071                                         emitSETC;
7072                                 }
7073                                 for (i = size-1; i >= 0; i--) {
7074                                         if (same && !offr) {
7075                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7076                                         } else {
7077                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7078                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7079                                         }
7080                                 } // for i
7081                         } // if (offr)
7082                         break;
7083                         
7084                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7085                         /* works in-place/with offr as well */
7086                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7087                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7088                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7089
7090                         for (i = 1; i < size; i++)
7091                         {
7092                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7093                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7094                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7095                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7096                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7097                         } // for i
7098
7099                         if (sign)
7100                         {
7101                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7102                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7103                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7104                         } // if
7105                         break;
7106                         
7107                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7108                         /* works in-place/with offr as well */
7109                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7110                         for (i = 0; i < size-1; i++) {
7111                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7112                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7113                         } // for i
7114                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7115                         if (!sign) {
7116                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7117                         } else {
7118                                 emitSKPNC;
7119                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7120                         }
7121                         break;
7122                 
7123                 default:
7124                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7125                         shiftRight_Left2ResultLit (result, result, 1, sign);
7126                         return; /* prevent sign extending result again */
7127                         break;
7128                 } // switch
7129         } // if
7130
7131         addSign (result, size, sign);
7132 }
7133
7134 #if 0
7135 /*-----------------------------------------------------------------*/
7136 /* shiftL2Left2Result - shift left two bytes from left to result   */
7137 /*-----------------------------------------------------------------*/
7138 static void shiftL2Left2Result (operand *left, int offl,
7139                                                                 operand *result, int offr, int shCount)
7140 {
7141         FENTRY;
7142         
7143         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7144         
7145         if(pic14_sameRegs(AOP(result), AOP(left))) {
7146                 switch(shCount) {
7147                 case 0:
7148                         break;
7149                 case 1:
7150                 case 2:
7151                 case 3:
7152                         
7153                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7154                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7155                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7156                         
7157                         while(--shCount) {
7158                                 emitCLRC;
7159                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7160                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7161                         }
7162                         
7163                         break;
7164                 case 4:
7165                 case 5:
7166                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7167                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7168                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7169                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7170                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7171                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7172                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7173                         if(shCount >=5) {
7174                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7175                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7176                         }
7177                         break;
7178                 case 6:
7179                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7180                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7181                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7182                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7183                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7184                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7185                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7186                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7187                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7188                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7189                         break;
7190                 case 7:
7191                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7192                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7193                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7194                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7195                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7196                 }
7197                 
7198         } else {
7199                 switch(shCount) {
7200                 case 0:
7201                         break;
7202                 case 1:
7203                 case 2:
7204                 case 3:
7205                 /* note, use a mov/add for the shift since the mov has a
7206                         chance of getting optimized out */
7207                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7208                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7209                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7210                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7211                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7212                         
7213                         while(--shCount) {
7214                                 emitCLRC;
7215                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7216                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7217                         }
7218                         break;
7219                         
7220                 case 4:
7221                 case 5:
7222                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7223                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7224                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7225                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7226                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7227                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7228                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7229                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7230                         
7231                         
7232                         if(shCount == 5) {
7233                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7234                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7235                         }
7236                         break;
7237                 case 6:
7238                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7239                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7240                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7241                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7242                         
7243                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7244                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7245                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7246                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7247                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7248                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7249                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7250                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7251                         break;
7252                 case 7:
7253                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7254                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7255                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7256                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7257                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7258                 }
7259         }
7260         
7261 }
7262
7263 /*-----------------------------------------------------------------*/
7264 /* shiftR2Left2Result - shift right two bytes from left to result  */
7265 /*-----------------------------------------------------------------*/
7266 static void shiftR2Left2Result (operand *left, int offl,
7267                                                                 operand *result, int offr,
7268                                                                 int shCount, int sign)
7269 {
7270         int same=0;
7271         
7272         FENTRY;
7273         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7274         same = pic14_sameRegs(AOP(result), AOP(left));
7275         
7276         if(same && ((offl + MSB16) == offr)){
7277                 same=1;
7278                 /* don't crash result[offr] */
7279                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7280                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7281         }
7282         /* else {
7283         movLeft2Result(left,offl, result, offr);
7284         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7285         }
7286         */
7287         /* a:x >> shCount (x = lsb(result))*/
7288         /*
7289         if(sign)
7290         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7291         else {
7292         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7293         */
7294         switch(shCount) {
7295         case 0:
7296                 break;
7297         case 1:
7298         case 2:
7299         case 3:
7300                 if(sign)
7301                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7302                 else
7303                         emitCLRC;
7304                 
7305                 if(same) {
7306                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7307                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7308                 } else {
7309                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7310                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7311                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7312                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7313                 }
7314                 
7315                 while(--shCount) {
7316                         if(sign)
7317                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7318                         else
7319                                 emitCLRC;
7320                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7321                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7322                 }
7323                 break;
7324         case 4:
7325         case 5:
7326                 if(same) {
7327                         
7328                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7329                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7330                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7331                         
7332                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7333                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7334                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7335                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7336                 } else {
7337                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7338                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7339                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7340                         
7341                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7342                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7343                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7344                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7345                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7346                 }
7347                 
7348                 if(shCount >=5) {
7349                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7350                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7351                 }
7352                 
7353                 if(sign) {
7354                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7355                         emitpcode(POC_BTFSC, 
7356                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7357                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7358                 }
7359                 
7360                 break;
7361                 
7362         case 6:
7363                 if(same) {
7364                         
7365                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7366                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7367                         
7368                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7369                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7370                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7371                         emitpcode(POC_ANDLW,popGetLit(0x03));
7372                         if(sign) {
7373                                 emitpcode(POC_BTFSC, 
7374                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7375                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7376                         }
7377                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7378                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7379                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7380                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7381                 } else {
7382                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7383                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7384                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7385                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7386                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7387                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7388                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7389                         emitpcode(POC_ANDLW,popGetLit(0x03));
7390                         if(sign) {
7391                                 emitpcode(POC_BTFSC, 
7392                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7393                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7394                         }
7395                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7396                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7397                         
7398                         
7399                 }
7400                 
7401                 break;
7402         case 7:
7403                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7404                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7405                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7406                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7407                 if(sign) {
7408                         emitSKPNC;
7409                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7410                 } else 
7411                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7412   }
7413 }
7414
7415 /*-----------------------------------------------------------------*/
7416 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7417 /*-----------------------------------------------------------------*/
7418 static void shiftLLeftOrResult (operand *left, int offl,
7419                                                                 operand *result, int offr, int shCount)
7420 {
7421         FENTRY;
7422         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7423         
7424         /* shift left accumulator */
7425         AccLsh(left,offl,shCount);
7426         /* or with result */
7427         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7428         assert ( !"broken (modifies left, fails for left==result))" );
7429 }
7430
7431 /*-----------------------------------------------------------------*/
7432 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7433 /*-----------------------------------------------------------------*/
7434 static void shiftRLeftOrResult (operand *left, int offl,
7435                                                                 operand *result, int offr, int shCount)
7436 {
7437         FENTRY;
7438         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7439         
7440         /* shift right accumulator */
7441         AccRsh(left,offl,shCount);
7442         /* or with result */
7443         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7444         assert ( !"broken (modifies left, fails for left==result))" );
7445 }
7446
7447 /*-----------------------------------------------------------------*/
7448 /* genlshOne - left shift a one byte quantity by known count       */
7449 /*-----------------------------------------------------------------*/
7450 static void genlshOne (operand *result, operand *left, int shCount)
7451 {       
7452         FENTRY;
7453         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7454         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7455 }
7456
7457 /*-----------------------------------------------------------------*/
7458 /* genlshTwo - left shift two bytes by known amount != 0           */
7459 /*-----------------------------------------------------------------*/
7460 static void genlshTwo (operand *result,operand *left, int shCount)
7461 {
7462         int size;
7463         
7464         FENTRY;
7465         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7466         size = pic14_getDataSize(result);
7467         
7468         /* if shCount >= 8 */
7469         if (shCount >= 8) {
7470                 shCount -= 8 ;
7471                 
7472                 if (size > 1){
7473                         if (shCount)
7474                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7475                         else 
7476                                 movLeft2Result(left, LSB, result, MSB16);
7477                 }
7478                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7479         }
7480         
7481         /*  1 <= shCount <= 7 */
7482         else {  
7483                 if(size == 1)
7484                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7485                 else 
7486                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7487         }
7488 }
7489
7490 /*-----------------------------------------------------------------*/
7491 /* shiftLLong - shift left one long from left to result            */
7492 /* offl = LSB or MSB16                                             */
7493 /*-----------------------------------------------------------------*/
7494 static void shiftLLong (operand *left, operand *result, int offr )
7495 {
7496         char *l;
7497         int size = AOP_SIZE(result);
7498         
7499         FENTRY;
7500         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7501         if(size >= LSB+offr){
7502                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7503                 MOVA(l);
7504                 pic14_emitcode("add","a,acc");
7505                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7506                         size >= MSB16+offr && offr != LSB )
7507                         pic14_emitcode("xch","a,%s",
7508                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7509                 else      
7510                         aopPut(AOP(result),"a",LSB+offr);
7511         }
7512         
7513         if(size >= MSB16+offr){
7514                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7515                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7516                         MOVA(l);
7517                 }
7518                 pic14_emitcode("rlc","a");
7519                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7520                         size >= MSB24+offr && offr != LSB)
7521                         pic14_emitcode("xch","a,%s",
7522                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7523                 else      
7524                         aopPut(AOP(result),"a",MSB16+offr);
7525         }
7526         
7527         if(size >= MSB24+offr){
7528                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7529                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7530                         MOVA(l);
7531                 }
7532                 pic14_emitcode("rlc","a");
7533                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7534                         size >= MSB32+offr && offr != LSB )
7535                         pic14_emitcode("xch","a,%s",
7536                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7537                 else      
7538                         aopPut(AOP(result),"a",MSB24+offr);
7539         }
7540         
7541         if(size > MSB32+offr){
7542                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7543                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7544                         MOVA(l);  
7545                 }
7546                 pic14_emitcode("rlc","a");
7547                 aopPut(AOP(result),"a",MSB32+offr);
7548         }
7549         if(offr != LSB)
7550                 aopPut(AOP(result),zero,LSB);       
7551 }
7552
7553 /*-----------------------------------------------------------------*/
7554 /* genlshFour - shift four byte by a known amount != 0             */
7555 /*-----------------------------------------------------------------*/
7556 static void genlshFour (operand *result, operand *left, int shCount)
7557 {
7558         int size;
7559         
7560         FENTRY;
7561         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7562         size = AOP_SIZE(result);
7563         
7564         /* if shifting more that 3 bytes */
7565         if (shCount >= 24 ) {
7566                 shCount -= 24;
7567                 if (shCount)
7568                 /* lowest order of left goes to the highest
7569                 order of the destination */
7570                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7571                 else
7572                         movLeft2Result(left, LSB, result, MSB32);
7573                 aopPut(AOP(result),zero,LSB);
7574                 aopPut(AOP(result),zero,MSB16);
7575                 aopPut(AOP(result),zero,MSB32);
7576                 return;
7577         }
7578         
7579         /* more than two bytes */
7580         else if ( shCount >= 16 ) {
7581                 /* lower order two bytes goes to higher order two bytes */
7582                 shCount -= 16;
7583                 /* if some more remaining */
7584                 if (shCount)
7585                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7586                 else {
7587                         movLeft2Result(left, MSB16, result, MSB32);
7588                         movLeft2Result(left, LSB, result, MSB24);
7589                 }
7590                 aopPut(AOP(result),zero,MSB16);
7591                 aopPut(AOP(result),zero,LSB);
7592                 return;
7593         }    
7594         
7595         /* if more than 1 byte */
7596         else if ( shCount >= 8 ) {
7597                 /* lower order three bytes goes to higher order  three bytes */
7598                 shCount -= 8;
7599                 if(size == 2){
7600                         if(shCount)
7601                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7602                         else
7603                                 movLeft2Result(left, LSB, result, MSB16);
7604                 }
7605                 else{   /* size = 4 */
7606                         if(shCount == 0){
7607                                 movLeft2Result(left, MSB24, result, MSB32);
7608                                 movLeft2Result(left, MSB16, result, MSB24);
7609                                 movLeft2Result(left, LSB, result, MSB16);
7610                                 aopPut(AOP(result),zero,LSB);
7611                         }
7612                         else if(shCount == 1)
7613                                 shiftLLong(left, result, MSB16);
7614                         else{
7615                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7616                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7617                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7618                                 aopPut(AOP(result),zero,LSB);
7619                         }
7620                 }
7621         }
7622         
7623         /* 1 <= shCount <= 7 */
7624         else if(shCount <= 2){
7625                 shiftLLong(left, result, LSB);
7626                 if(shCount == 2)
7627                         shiftLLong(result, result, LSB);
7628         }
7629         /* 3 <= shCount <= 7, optimize */
7630         else{
7631                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7632                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7633                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7634         }
7635 }
7636 #endif
7637
7638 #if 0
7639 /*-----------------------------------------------------------------*/
7640 /* genLeftShiftLiteral - left shifting by known count              */
7641 /*-----------------------------------------------------------------*/
7642 static void genLeftShiftLiteral (operand *left,
7643                                                                  operand *right,
7644                                                                  operand *result,
7645                                                                  iCode *ic)
7646 {    
7647         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7648         //int size;
7649         
7650         FENTRY;
7651         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7652         freeAsmop(right,NULL,ic,TRUE);
7653         
7654         aopOp(left,ic,FALSE);
7655         aopOp(result,ic,FALSE);
7656
7657         size = getSize(operandType(result));
7658         
7659 #if VIEW_SIZE
7660         pic14_emitcode("; shift left ","result %d, left %d",size,
7661                 AOP_SIZE(left));
7662 #endif
7663         
7664         /* I suppose that the left size >= result size */
7665         if(shCount == 0){
7666                 while(size--){
7667                         movLeft2Result(left, size, result, size);
7668                 }
7669         }
7670         
7671         else if(shCount >= (size * 8))
7672                 while(size--)
7673                         aopPut(AOP(result),zero,size);
7674                 else{
7675                         switch (size) {
7676                         case 1:
7677                                 genlshOne (result,left,shCount);
7678                                 break;
7679                                 
7680                         case 2:
7681                         case 3:
7682                                 genlshTwo (result,left,shCount);
7683                                 break;
7684                                 
7685                         case 4:
7686                                 genlshFour (result,left,shCount);
7687                                 break;
7688                         }
7689                 }
7690                 freeAsmop(left,NULL,ic,TRUE);
7691                 freeAsmop(result,NULL,ic,TRUE);
7692 }
7693 #endif
7694
7695 /*-----------------------------------------------------------------*
7696 * genMultiAsm - repeat assembly instruction for size of register.
7697 * if endian == 1, then the high byte (i.e base address + size of 
7698 * register) is used first else the low byte is used first;
7699 *-----------------------------------------------------------------*/
7700 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7701 {
7702         
7703         int offset = 0;
7704         
7705         FENTRY;
7706         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7707         
7708         if(!reg)
7709                 return;
7710         
7711         if(!endian) {
7712                 endian = 1;
7713         } else {
7714                 endian = -1;
7715                 offset = size-1;
7716         }
7717         
7718         while(size--) {
7719                 emitpcode(poc,    popGet(AOP(reg),offset));
7720                 offset += endian;
7721         }
7722         
7723 }
7724 /*-----------------------------------------------------------------*/
7725 /* genLeftShift - generates code for left shifting                 */
7726 /*-----------------------------------------------------------------*/
7727 static void genLeftShift (iCode *ic)
7728 {
7729         operand *left,*right, *result;
7730         int size, offset;
7731         unsigned long lit = 0L;
7732         char *l;
7733         symbol *tlbl , *tlbl1;
7734         pCodeOp *pctemp;
7735         
7736         FENTRY;
7737         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7738         
7739         right = IC_RIGHT(ic);
7740         left  = IC_LEFT(ic);
7741         result = IC_RESULT(ic);
7742         
7743         aopOp(right,ic,FALSE);
7744         aopOp(left,ic,FALSE);
7745         aopOp(result,ic,FALSE);
7746         
7747         
7748         /* if the shift count is known then do it 
7749         as efficiently as possible */
7750         if (AOP_TYPE(right) == AOP_LIT) {
7751                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7752                 return ;
7753         }
7754         
7755         /* shift count is unknown then we have to form 
7756         a loop get the loop count in B : Note: we take
7757         only the lower order byte since shifting
7758         more that 32 bits make no sense anyway, ( the
7759         largest size of an object can be only 32 bits ) */  
7760         
7761         /* this code fails for RIGHT == RESULT */
7762         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7763         
7764         /* now move the left to the result if they are not the
7765         same */
7766         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7767                 AOP_SIZE(result) > 1) {
7768                 
7769                 size = AOP_SIZE(result);
7770                 offset=0;
7771                 while (size--) {
7772                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7773                         if (*l == '@' && (IS_AOP_PREG(result))) {
7774                                 
7775                                 pic14_emitcode("mov","a,%s",l);
7776                                 aopPut(AOP(result),"a",offset);
7777                         } else {
7778                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7779                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7780                                 //aopPut(AOP(result),l,offset);
7781                         }
7782                         offset++;
7783                 }
7784         }
7785         
7786         if(AOP_TYPE(left) == AOP_LIT)
7787                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7788
7789         size = AOP_SIZE(result);
7790         
7791         /* if it is only one byte then */
7792         if (size == 1) {
7793                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7794                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7795                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7796                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7797                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7798                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7799                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7800                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7801                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7802                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7803                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7804                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7805                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7806                 } else {
7807                         
7808                         tlbl = newiTempLabel(NULL);
7809                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7810                                 mov2w (AOP(left), 0);
7811                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7812                         }
7813                         
7814                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7815                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7816                         emitpLabel(tlbl->key);
7817                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7818                         emitpcode(POC_ADDLW,  popGetLit(1));
7819                         emitSKPC;
7820                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7821                 }
7822                 goto release ;
7823         }
7824         
7825         if (pic14_sameRegs(AOP(left),AOP(result))) {
7826                 
7827                 tlbl = newiTempLabel(NULL);
7828                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7829                 genMultiAsm(POC_RRF, result, size,1);
7830                 emitpLabel(tlbl->key);
7831                 genMultiAsm(POC_RLF, result, size,0);
7832                 emitpcode(POC_ADDLW,  popGetLit(1));
7833                 emitSKPC;
7834                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7835                 goto release;
7836         }
7837         
7838         //tlbl = newiTempLabel(NULL);
7839         //offset = 0 ;   
7840         //tlbl1 = newiTempLabel(NULL);
7841         
7842         //reAdjustPreg(AOP(result));    
7843         
7844         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7845         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7846         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7847         //MOVA(l);
7848         //pic14_emitcode("add","a,acc");         
7849         //aopPut(AOP(result),"a",offset++);
7850         //while (--size) {
7851         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7852         //  MOVA(l);
7853         //  pic14_emitcode("rlc","a");         
7854         //  aopPut(AOP(result),"a",offset++);
7855         //}
7856         //reAdjustPreg(AOP(result));
7857         
7858         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7859         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7860         
7861         
7862         tlbl = newiTempLabel(NULL);
7863         tlbl1= newiTempLabel(NULL);
7864         
7865         size = AOP_SIZE(result);
7866         offset = 1;
7867         
7868         pctemp = popGetTempReg();  /* grab a temporary working register. */
7869         
7870         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7871         
7872         /* offset should be 0, 1 or 3 */
7873         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7874         emitSKPNZ;
7875         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7876         
7877         emitpcode(POC_MOVWF, pctemp);
7878         
7879         
7880         emitpLabel(tlbl->key);
7881         
7882         emitCLRC;
7883         emitpcode(POC_RLF,  popGet(AOP(result),0));
7884         while(--size)
7885                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7886         
7887         emitpcode(POC_DECFSZ,  pctemp);
7888         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7889         emitpLabel(tlbl1->key);
7890         
7891         popReleaseTempReg(pctemp);
7892         
7893         
7894 release:
7895         freeAsmop (right,NULL,ic,TRUE);
7896         freeAsmop(left,NULL,ic,TRUE);
7897         freeAsmop(result,NULL,ic,TRUE);
7898 }
7899
7900 #if 0
7901 /*-----------------------------------------------------------------*/
7902 /* genrshOne - right shift a one byte quantity by known count      */
7903 /*-----------------------------------------------------------------*/
7904 static void genrshOne (operand *result, operand *left,
7905                                            int shCount, int sign)
7906 {
7907         FENTRY;
7908         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7909         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7910 }
7911
7912 /*-----------------------------------------------------------------*/
7913 /* genrshTwo - right shift two bytes by known amount != 0          */
7914 /*-----------------------------------------------------------------*/
7915 static void genrshTwo (operand *result,operand *left,
7916                                            int shCount, int sign)
7917 {
7918         FENTRY;
7919         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7920         /* if shCount >= 8 */
7921         if (shCount >= 8) {
7922                 shCount -= 8 ;
7923                 if (shCount)
7924                         shiftR1Left2Result(left, MSB16, result, LSB,
7925                         shCount, sign);
7926                 else
7927                         movLeft2Result(left, MSB16, result, LSB);
7928                 
7929                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7930                 
7931                 if(sign) {
7932                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7933                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7934                 }
7935         }
7936         
7937         /*  1 <= shCount <= 7 */
7938         else
7939                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7940 }
7941
7942 /*-----------------------------------------------------------------*/
7943 /* shiftRLong - shift right one long from left to result           */
7944 /* offl = LSB or MSB16                                             */
7945 /*-----------------------------------------------------------------*/
7946 static void shiftRLong (operand *left, int offl,
7947                                                 operand *result, int sign)
7948 {
7949         int size, same;
7950         
7951         FENTRY;
7952         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7953         
7954         size = AOP_SIZE(left);
7955         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7956         
7957         if (sign)
7958                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7959         else
7960                 emitCLRC;
7961
7962         assert (offl >= 0 && offl < size);
7963
7964         same = pic14_sameRegs (AOP(left), AOP(result));
7965
7966         /* perform the shift */
7967         while (size--)
7968         {
7969                 if (same && !offl) {
7970                         emitpcode (POC_RRF, popGet (AOP(result), size));
7971                 } else {
7972                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7973                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7974                 }
7975         } // while
7976
7977         addSign (result, AOP_SIZE(left) - offl, sign);
7978 }
7979
7980 /*-----------------------------------------------------------------*/
7981 /* genrshFour - shift four byte by a known amount != 0             */
7982 /*-----------------------------------------------------------------*/
7983 static void genrshFour (operand *result, operand *left,
7984                                                 int shCount, int sign)
7985 {
7986         FENTRY;
7987         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7988         /* if shifting more that 3 bytes */
7989         if(shCount >= 24 ) {
7990                 shCount -= 24;
7991                 if(shCount)
7992                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7993                 else
7994                         movLeft2Result(left, MSB32, result, LSB);
7995                 
7996                 addSign(result, MSB16, sign);
7997         }
7998         else if(shCount >= 16){
7999                 shCount -= 16;
8000                 if(shCount)
8001                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8002                 else{
8003                         movLeft2Result(left, MSB24, result, LSB);
8004                         movLeft2Result(left, MSB32, result, MSB16);
8005                 }
8006                 addSign(result, MSB24, sign);
8007         }
8008         else if(shCount >= 8){
8009                 shCount -= 8;
8010                 if(shCount == 1)
8011                         shiftRLong(left, MSB16, result, sign);
8012                 else if(shCount == 0){
8013                         movLeft2Result(left, MSB16, result, LSB);
8014                         movLeft2Result(left, MSB24, result, MSB16);
8015                         movLeft2Result(left, MSB32, result, MSB24);
8016                         addSign(result, MSB32, sign);
8017                 }
8018                 else{
8019                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8020                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8021                         /* the last shift is signed */
8022                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8023                         addSign(result, MSB32, sign);
8024                 }
8025         }
8026         else{   /* 1 <= shCount <= 7 */
8027                 if(shCount <= 2){
8028                         shiftRLong(left, LSB, result, sign);
8029                         if(shCount == 2)
8030                                 shiftRLong(result, LSB, result, sign);
8031                 }
8032                 else{
8033                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8034                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8035                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8036                 }
8037         }
8038 }
8039
8040 /*-----------------------------------------------------------------*/
8041 /* genRightShiftLiteral - right shifting by known count            */
8042 /*-----------------------------------------------------------------*/
8043 static void genRightShiftLiteral (operand *left,
8044                                                                   operand *right,
8045                                                                   operand *result,
8046                                                                   iCode *ic,
8047                                                                   int sign)
8048 {    
8049         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8050         int lsize,res_size;
8051         
8052         FENTRY;
8053         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8054         freeAsmop(right,NULL,ic,TRUE);
8055         
8056         aopOp(left,ic,FALSE);
8057         aopOp(result,ic,FALSE);
8058         
8059 #if VIEW_SIZE
8060         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8061                 AOP_SIZE(left));
8062 #endif
8063         
8064         lsize = pic14_getDataSize(left);
8065         res_size = pic14_getDataSize(result);
8066         /* test the LEFT size !!! */
8067         
8068         /* I suppose that the left size >= result size */
8069         if(shCount == 0){
8070                 while(res_size--)
8071                         movLeft2Result(left, res_size, result, res_size);
8072         }
8073         
8074         else if(shCount >= (lsize * 8)){
8075                 
8076                 if(res_size == 1) {
8077                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8078                         if(sign) {
8079                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8080                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8081                         }
8082                 } else {
8083                         
8084                         if(sign) {
8085                                 emitpcode(POC_MOVLW, popGetLit(0));
8086                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8087                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8088                                 while(res_size--)
8089                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8090                                 
8091                         } else {
8092                                 
8093                                 while(res_size--)
8094                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8095                         }
8096                 }
8097         } else {
8098                 
8099                 switch (res_size) {
8100                 case 1:
8101                         genrshOne (result,left,shCount,sign);
8102                         break;
8103                         
8104                 case 2:
8105                         genrshTwo (result,left,shCount,sign);
8106                         break;
8107                         
8108                 case 4:
8109                         genrshFour (result,left,shCount,sign);
8110                         break;
8111                 default :
8112                         break;
8113                 }
8114                 
8115         }
8116
8117         freeAsmop(left,NULL,ic,TRUE);
8118         freeAsmop(result,NULL,ic,TRUE);
8119 }
8120 #endif
8121
8122 /*-----------------------------------------------------------------*/
8123 /* genSignedRightShift - right shift of signed number              */
8124 /*-----------------------------------------------------------------*/
8125 static void genSignedRightShift (iCode *ic)
8126 {
8127         operand *right, *left, *result;
8128         int size, offset;
8129         //  char *l;
8130         symbol *tlbl, *tlbl1 ;
8131         pCodeOp *pctemp;
8132         
8133         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8134         
8135         /* we do it the hard way put the shift count in b
8136         and loop thru preserving the sign */
8137         FENTRY;
8138         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8139         
8140         right = IC_RIGHT(ic);
8141         left  = IC_LEFT(ic);
8142         result = IC_RESULT(ic);
8143         
8144         aopOp(right,ic,FALSE);  
8145         aopOp(left,ic,FALSE);
8146         aopOp(result,ic,FALSE);
8147         
8148         
8149         if ( AOP_TYPE(right) == AOP_LIT) {
8150                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8151                 //genRightShiftLiteral (left,right,result,ic,1);
8152                 return ;
8153         }
8154         /* shift count is unknown then we have to form 
8155         a loop get the loop count in B : Note: we take
8156         only the lower order byte since shifting
8157         more that 32 bits make no sense anyway, ( the
8158         largest size of an object can be only 32 bits ) */  
8159         
8160         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8161         //pic14_emitcode("inc","b");
8162         //freeAsmop (right,NULL,ic,TRUE);
8163         //aopOp(left,ic,FALSE);
8164         //aopOp(result,ic,FALSE);
8165         
8166         /* now move the left to the result if they are not the
8167         same */
8168         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8169                 AOP_SIZE(result) > 1) {
8170                 
8171                 size = AOP_SIZE(result);
8172                 offset=0;
8173                 while (size--) { 
8174                         /*
8175                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8176                         if (*l == '@' && IS_AOP_PREG(result)) {
8177                                 pic14_emitcode("mov","a,%s",l);
8178                                 aopPut(AOP(result),"a",offset);
8179                         } else
8180                         aopPut(AOP(result),l,offset);
8181                         */
8182                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8183                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8184                         
8185                         offset++;
8186                 }
8187         }
8188         
8189         /* mov the highest order bit to OVR */    
8190         tlbl = newiTempLabel(NULL);
8191         tlbl1= newiTempLabel(NULL);
8192         
8193         size = AOP_SIZE(result);
8194         offset = size - 1;
8195         
8196         pctemp = popGetTempReg();  /* grab a temporary working register. */
8197         
8198         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8199         
8200         /* offset should be 0, 1 or 3 */
8201         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8202         emitSKPNZ;
8203         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8204         
8205         emitpcode(POC_MOVWF, pctemp);
8206         
8207         
8208         emitpLabel(tlbl->key);
8209         
8210         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8211         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8212         
8213         while(--size) {
8214                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8215         }
8216         
8217         emitpcode(POC_DECFSZ,  pctemp);
8218         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8219         emitpLabel(tlbl1->key);
8220         
8221         popReleaseTempReg(pctemp);
8222 #if 0
8223         size = AOP_SIZE(result);
8224         offset = size - 1;
8225         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8226         pic14_emitcode("rlc","a");
8227         pic14_emitcode("mov","ov,c");
8228         /* if it is only one byte then */
8229         if (size == 1) {
8230                 l = aopGet(AOP(left),0,FALSE,FALSE);
8231                 MOVA(l);
8232                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8233                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8234                 pic14_emitcode("mov","c,ov");
8235                 pic14_emitcode("rrc","a");
8236                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8237                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8238                 aopPut(AOP(result),"a",0);
8239                 goto release ;
8240         }
8241         
8242         reAdjustPreg(AOP(result));
8243         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8244         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8245         pic14_emitcode("mov","c,ov");
8246         while (size--) {
8247                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8248                 MOVA(l);
8249                 pic14_emitcode("rrc","a");         
8250                 aopPut(AOP(result),"a",offset--);
8251         }
8252         reAdjustPreg(AOP(result));
8253         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8254         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8255         
8256 release:
8257 #endif
8258         
8259         freeAsmop(left,NULL,ic,TRUE);
8260         freeAsmop(result,NULL,ic,TRUE);
8261         freeAsmop(right,NULL,ic,TRUE);
8262 }
8263
8264 /*-----------------------------------------------------------------*/
8265 /* genRightShift - generate code for right shifting                */
8266 /*-----------------------------------------------------------------*/
8267 static void genRightShift (iCode *ic)
8268 {
8269         operand *right, *left, *result;
8270         sym_link *retype ;
8271         int size, offset;
8272         char *l;
8273         symbol *tlbl, *tlbl1 ;
8274         
8275         FENTRY;
8276         /* if signed then we do it the hard way preserve the
8277         sign bit moving it inwards */
8278         retype = getSpec(operandType(IC_RESULT(ic)));
8279         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8280         
8281         if (!SPEC_USIGN(retype)) {
8282                 genSignedRightShift (ic);
8283                 return ;
8284         }
8285         
8286         /* signed & unsigned types are treated the same : i.e. the
8287         signed is NOT propagated inwards : quoting from the
8288         ANSI - standard : "for E1 >> E2, is equivalent to division
8289         by 2**E2 if unsigned or if it has a non-negative value,
8290         otherwise the result is implementation defined ", MY definition
8291         is that the sign does not get propagated */
8292         
8293         right = IC_RIGHT(ic);
8294         left  = IC_LEFT(ic);
8295         result = IC_RESULT(ic);
8296         
8297         aopOp(right,ic,FALSE);
8298         aopOp(left,ic,FALSE);
8299         aopOp(result,ic,FALSE);
8300         
8301         /* if the shift count is known then do it 
8302         as efficiently as possible */
8303         if (AOP_TYPE(right) == AOP_LIT) {
8304                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
8305                 //genRightShiftLiteral (left,right,result,ic, 0);
8306                 return ;
8307         }
8308         
8309         /* shift count is unknown then we have to form 
8310         a loop get the loop count in B : Note: we take
8311         only the lower order byte since shifting
8312         more that 32 bits make no sense anyway, ( the
8313         largest size of an object can be only 32 bits ) */  
8314         
8315         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8316         pic14_emitcode("inc","b");
8317         
8318         /* now move the left to the result if they are not the
8319         same */
8320         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8321                 AOP_SIZE(result) > 1) {
8322                 
8323                 size = AOP_SIZE(result);
8324                 offset=0;
8325                 while (size--) {
8326                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8327                         if (*l == '@' && IS_AOP_PREG(result)) {
8328                                 
8329                                 pic14_emitcode("mov","a,%s",l);
8330                                 aopPut(AOP(result),"a",offset);
8331                         } else
8332                                 aopPut(AOP(result),l,offset);
8333                         offset++;
8334                 }
8335         }
8336         
8337         tlbl = newiTempLabel(NULL);
8338         tlbl1= newiTempLabel(NULL);
8339         size = AOP_SIZE(result);
8340         offset = size - 1;
8341         
8342         /* if it is only one byte then */
8343         if (size == 1) {
8344                 
8345                 tlbl = newiTempLabel(NULL);
8346                 if (!pic14_sameRegs(AOP(left),AOP(result))) {
8347                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
8348                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
8349                 }
8350                 
8351                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
8352                 emitpcode(POC_RLF,    popGet(AOP(result),0));
8353                 emitpLabel(tlbl->key);
8354                 emitpcode(POC_RRF,    popGet(AOP(result),0));
8355                 emitpcode(POC_ADDLW,  popGetLit(1));
8356                 emitSKPC;
8357                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8358                 
8359                 goto release ;
8360         }
8361         
8362         reAdjustPreg(AOP(result));
8363         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8364         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8365         CLRC;
8366         while (size--) {
8367                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8368                 MOVA(l);
8369                 pic14_emitcode("rrc","a");         
8370                 aopPut(AOP(result),"a",offset--);
8371         }
8372         reAdjustPreg(AOP(result));
8373         
8374         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8375         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8376         
8377 release:
8378         freeAsmop(left,NULL,ic,TRUE);
8379         freeAsmop (right,NULL,ic,TRUE);
8380         freeAsmop(result,NULL,ic,TRUE);
8381 }
8382
8383 /*-----------------------------------------------------------------*/
8384 /* genUnpackBits - generates code for unpacking bits               */
8385 /*-----------------------------------------------------------------*/
8386 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
8387 {    
8388         int shCnt;
8389         int offset = 0;       /* result byte offset */
8390         int rsize;            /* result size */
8391         int rlen = 0;         /* remaining bitfield length */
8392         sym_link *etype;      /* bitfield type information */
8393         int blen;             /* bitfield length */
8394         int bstr;             /* bitfield starting bit within byte */
8395
8396         FENTRY;
8397         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8398         etype = getSpec(operandType(result));
8399         rsize = getSize (operandType (result));
8400         blen = SPEC_BLEN (etype);
8401         bstr = SPEC_BSTR (etype);
8402         
8403         /* single bit field case */
8404         if (blen == 1) {
8405                 if (ifx) { /* that is for an if statement */
8406                         pCodeOp *pcop;
8407                         resolvedIfx rIfx;
8408                         resolveIfx(&rIfx,ifx);
8409                         if (ptype == -1) /* direct */
8410                                 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8411                         else
8412                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8413                         emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8414                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8415                         ifx->generated=1;
8416                 } else {
8417                         pCodeOp *pcop;
8418                         
8419                         if (ptype == -1) /* direct */
8420                                 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8421                         else
8422                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8423                         emitpcode(POC_BTFSC,pcop);
8424                         emitpcode(POC_BSF,newpCodeOpBit(aopGet(AOP(result), 0,FALSE,FALSE),bstr,0));
8425                         if (ptype == -1) /* direct */
8426                                 pcop = newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),bstr,0);
8427                         else
8428                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8429                         emitpcode(POC_BTFSS,pcop);
8430                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0));
8431                 }
8432                 return;
8433         }
8434
8435         {
8436           static int has_warned=0;
8437           if (!has_warned)
8438           {
8439             fprintf (stderr, "%s: bitfields with more than 1 bit are probably broken...", __FUNCTION__);
8440             has_warned=1;
8441           }
8442         }
8443
8444         /* read the first byte  */
8445         switch (ptype) {
8446                 
8447         case POINTER:
8448         case IPOINTER:
8449 //              pic14_emitcode("mov","a,@%s",rname);
8450                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8451                 break;
8452                 
8453         case PPOINTER:
8454                 pic14_emitcode("movx","a,@%s",rname);
8455                 break;
8456                 
8457         case FPOINTER:
8458                 pic14_emitcode("movx","a,@dptr");
8459                 break;
8460                 
8461         case CPOINTER:
8462                 pic14_emitcode("clr","a");
8463                 pic14_emitcode("movc","a","@a+dptr");
8464                 break;
8465                 
8466         case GPOINTER:
8467                 pic14_emitcode("lcall","__gptrget");
8468                 break;
8469         }
8470
8471         /* if we have bitdisplacement then it fits   */
8472         /* into this byte completely or if length is */
8473         /* less than a byte                          */
8474         if ((shCnt = SPEC_BSTR(etype)) || blen <= 8)  {
8475                 
8476                 /* shift right acc */
8477                 AccRsh(left,0,shCnt);
8478                 
8479                 pic14_emitcode("anl","a,#0x%02x",
8480                         ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8481                 aopPut(AOP(result),"a",offset);
8482                 return ;
8483         }
8484         
8485         /* bit field did not fit in a byte  */
8486         rlen = SPEC_BLEN(etype) - 8;
8487         aopPut(AOP(result),"a",offset++);
8488         
8489         while (1)  {
8490                 
8491                 switch (ptype) {
8492                 case POINTER:
8493                 case IPOINTER:
8494                         pic14_emitcode("inc","%s",rname);
8495                         pic14_emitcode("mov","a,@%s",rname);
8496                         break;
8497                         
8498                 case PPOINTER:
8499                         pic14_emitcode("inc","%s",rname);
8500                         pic14_emitcode("movx","a,@%s",rname);
8501                         break;
8502                         
8503                 case FPOINTER:
8504                         pic14_emitcode("inc","dptr");
8505                         pic14_emitcode("movx","a,@dptr");
8506                         break;
8507                         
8508                 case CPOINTER:
8509                         pic14_emitcode("clr","a");
8510                         pic14_emitcode("inc","dptr");
8511                         pic14_emitcode("movc","a","@a+dptr");
8512                         break;
8513                         
8514                 case GPOINTER:
8515                         pic14_emitcode("inc","dptr");
8516                         pic14_emitcode("lcall","__gptrget");
8517                         break;
8518                 }
8519                 
8520                 rlen -= 8;            
8521                 /* if we are done */
8522                 if ( rlen <= 0 )
8523                         break ;
8524                 
8525                 aopPut(AOP(result),"a",offset++);
8526                 
8527         }
8528         
8529         if (rlen) {
8530                 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8531                 aopPut(AOP(result),"a",offset);        
8532         }
8533         
8534         return ;
8535 }
8536
8537 #if 1
8538 /*-----------------------------------------------------------------*/
8539 /* genDataPointerGet - generates code when ptr offset is known     */
8540 /*-----------------------------------------------------------------*/
8541 static void genDataPointerGet (operand *left, 
8542         operand *result, 
8543         iCode *ic)
8544 {
8545         int size , offset = 0;
8546                 
8547         FENTRY;
8548         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8549         
8550         
8551         /* optimization - most of the time, left and result are the same
8552         * address, but different types. for the pic code, we could omit
8553         * the following
8554         */
8555         aopOp(result,ic,TRUE);
8556         
8557         if (pic14_sameRegs (AOP(left), AOP(result)))
8558                 return;
8559         
8560         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8561         
8562         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8563         
8564         size = AOP_SIZE(result);
8565         if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
8566         
8567         while (size--) {
8568                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8569                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8570                 offset++;
8571         }
8572         
8573         freeAsmop(left,NULL,ic,TRUE);
8574         freeAsmop(result,NULL,ic,TRUE);
8575 }
8576 #endif
8577 /*-----------------------------------------------------------------*/
8578 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8579 /*-----------------------------------------------------------------*/
8580 static void genNearPointerGet (operand *left, 
8581                                                            operand *result, 
8582                                                            iCode *ic)
8583 {
8584         asmop *aop = NULL;
8585         sym_link *ltype = operandType(left);
8586         sym_link *rtype = operandType(result);
8587         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8588         int direct = 0;
8589
8590         FENTRY;
8591         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8592         
8593         
8594         aopOp(left,ic,FALSE);
8595         
8596         /* if left is rematerialisable and
8597         result is not bit variable type and
8598         the left is pointer to data space i.e
8599         lower 128 bytes of space */
8600         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8601                 !IS_BITVAR(retype)         &&
8602                 DCL_TYPE(ltype) == POINTER) {
8603                 genDataPointerGet (left,result,ic);
8604                 return ;
8605         }
8606         
8607         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8608         aopOp (result,ic,FALSE);
8609         
8610         /* Check if can access directly instead of via a pointer */
8611         if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
8612                 direct = 1;
8613         }
8614
8615         /* If the pointer value is not in a the FSR then need to put it in */
8616         if (!AOP_INPREG(AOP(left)) && !direct) {
8617                 /* otherwise get a free pointer register */
8618                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8619                 if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */ 
8620                         emitpcode(POC_MOVLW, popGet(AOP(left),0));
8621                 else
8622                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
8623                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8624         }
8625         
8626         
8627 //      sym_link *etype;
8628         /* if bitfield then unpack the bits */
8629         if (IS_BITFIELD(retype)) 
8630                 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8631         else {
8632                 /* we have can just get the values */
8633                 int size = AOP_SIZE(result);
8634                 int offset = 0 ;  
8635                 
8636                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8637                 
8638                 while(size--) {
8639                         if (direct)
8640                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8641                         else
8642                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8643                         if (AOP_TYPE(result) == AOP_LIT) {
8644                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8645                         } else {
8646                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8647                         }
8648                         if (size && !direct)
8649                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8650                         offset++;
8651                 }
8652         }
8653         
8654         /* now some housekeeping stuff */
8655         if (aop) {
8656                 /* we had to allocate for this iCode */
8657                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8658                 freeAsmop(NULL,aop,ic,TRUE);
8659         } else { 
8660                 /* we did not allocate which means left
8661                 already in a pointer register, then
8662                 if size > 0 && this could be used again
8663                 we have to point it back to where it 
8664                 belongs */
8665                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8666                 if (AOP_SIZE(result) > 1 &&
8667                         !OP_SYMBOL(left)->remat &&
8668                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8669                         ic->depth )) {
8670                         int size = AOP_SIZE(result) - 1;
8671                         while (size--)
8672                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8673                 }
8674         }
8675         
8676         /* done */
8677         freeAsmop(left,NULL,ic,TRUE);
8678         freeAsmop(result,NULL,ic,TRUE);
8679
8680 }
8681
8682 /*-----------------------------------------------------------------*/
8683 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8684 /*-----------------------------------------------------------------*/
8685 static void genPagedPointerGet (operand *left, 
8686                                                                 operand *result, 
8687                                                                 iCode *ic)
8688 {
8689         asmop *aop = NULL;
8690         regs *preg = NULL ;
8691         char *rname ;
8692         sym_link *rtype, *retype;    
8693         
8694         FENTRY;
8695         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8696         
8697         rtype = operandType(result);
8698         retype= getSpec(rtype);
8699         
8700         aopOp(left,ic,FALSE);
8701         
8702         /* if the value is already in a pointer register
8703         then don't need anything more */
8704         if (!AOP_INPREG(AOP(left))) {
8705                 /* otherwise get a free pointer register */
8706                 aop = newAsmop(0);
8707                 preg = getFreePtr(ic,&aop,FALSE);
8708                 pic14_emitcode("mov","%s,%s",
8709                         preg->name,
8710                         aopGet(AOP(left),0,FALSE,TRUE));
8711                 rname = preg->name ;
8712         } else
8713                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8714         
8715         freeAsmop(left,NULL,ic,TRUE);
8716         aopOp (result,ic,FALSE);
8717         
8718         /* if bitfield then unpack the bits */
8719         if (IS_BITFIELD(retype)) 
8720                 genUnpackBits (result,left,rname,PPOINTER,0);
8721         else {
8722                 /* we have can just get the values */
8723                 int size = AOP_SIZE(result);
8724                 int offset = 0 ;  
8725                 
8726                 while (size--) {
8727                         
8728                         pic14_emitcode("movx","a,@%s",rname);
8729                         aopPut(AOP(result),"a",offset);
8730                         
8731                         offset++ ;
8732                         
8733                         if (size)
8734                                 pic14_emitcode("inc","%s",rname);
8735                 }
8736         }
8737         
8738         /* now some housekeeping stuff */
8739         if (aop) {
8740                 /* we had to allocate for this iCode */
8741                 freeAsmop(NULL,aop,ic,TRUE);
8742         } else { 
8743         /* we did not allocate which means left
8744         already in a pointer register, then
8745         if size > 0 && this could be used again
8746         we have to point it back to where it 
8747                 belongs */
8748                 if (AOP_SIZE(result) > 1 &&
8749                         !OP_SYMBOL(left)->remat &&
8750                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8751                         ic->depth )) {
8752                         int size = AOP_SIZE(result) - 1;
8753                         while (size--)
8754                                 pic14_emitcode("dec","%s",rname);
8755                 }
8756         }
8757         
8758         /* done */
8759         freeAsmop(result,NULL,ic,TRUE);
8760         
8761         
8762 }
8763
8764 /*-----------------------------------------------------------------*/
8765 /* genFarPointerGet - gget value from far space                    */
8766 /*-----------------------------------------------------------------*/
8767 static void genFarPointerGet (operand *left,
8768                                                           operand *result, iCode *ic)
8769 {
8770         int size, offset ;
8771         sym_link *retype = getSpec(operandType(result));
8772         
8773         FENTRY;
8774         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8775         
8776         aopOp(left,ic,FALSE);
8777         
8778         /* if the operand is already in dptr 
8779         then we do nothing else we move the value to dptr */
8780         if (AOP_TYPE(left) != AOP_STR) {
8781                 /* if this is remateriazable */
8782                 if (AOP_TYPE(left) == AOP_IMMD)
8783                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8784                 else { /* we need to get it byte by byte */
8785                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8786                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8787                         if (options.model == MODEL_FLAT24)
8788                         {
8789                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8790                         }
8791                 }
8792         }
8793         /* so dptr know contains the address */
8794         freeAsmop(left,NULL,ic,TRUE);
8795         aopOp(result,ic,FALSE);
8796         
8797         /* if bit then unpack */
8798         if (IS_BITFIELD(retype)) 
8799                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8800         else {
8801                 size = AOP_SIZE(result);
8802                 offset = 0 ;
8803                 
8804                 while (size--) {
8805                         pic14_emitcode("movx","a,@dptr");
8806                         aopPut(AOP(result),"a",offset++);
8807                         if (size)
8808                                 pic14_emitcode("inc","dptr");
8809                 }
8810         }
8811         
8812         freeAsmop(result,NULL,ic,TRUE);
8813 }
8814 #if 0
8815 /*-----------------------------------------------------------------*/
8816 /* genCodePointerGet - get value from code space                  */
8817 /*-----------------------------------------------------------------*/
8818 static void genCodePointerGet (operand *left,
8819                                                            operand *result, iCode *ic)
8820 {
8821         int size, offset ;
8822         sym_link *retype = getSpec(operandType(result));
8823         
8824         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8825         
8826         aopOp(left,ic,FALSE);
8827         
8828         /* if the operand is already in dptr 
8829         then we do nothing else we move the value to dptr */
8830         if (AOP_TYPE(left) != AOP_STR) {
8831                 /* if this is remateriazable */
8832                 if (AOP_TYPE(left) == AOP_IMMD)
8833                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8834                 else { /* we need to get it byte by byte */
8835                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8836                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8837                         if (options.model == MODEL_FLAT24)
8838                         {
8839                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8840                         }
8841                 }
8842         }
8843         /* so dptr know contains the address */
8844         freeAsmop(left,NULL,ic,TRUE);
8845         aopOp(result,ic,FALSE);
8846         
8847         /* if bit then unpack */
8848         if (IS_BITFIELD(retype)) 
8849                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8850         else {
8851                 size = AOP_SIZE(result);
8852                 offset = 0 ;
8853                 
8854                 while (size--) {
8855                         pic14_emitcode("clr","a");
8856                         pic14_emitcode("movc","a,@a+dptr");
8857                         aopPut(AOP(result),"a",offset++);
8858                         if (size)
8859                                 pic14_emitcode("inc","dptr");
8860                 }
8861         }
8862         
8863         freeAsmop(result,NULL,ic,TRUE);
8864 }
8865 #endif
8866 /*-----------------------------------------------------------------*/
8867 /* genGenPointerGet - gget value from generic pointer space        */
8868 /*-----------------------------------------------------------------*/
8869 static void genGenPointerGet (operand *left,
8870                                                           operand *result, iCode *ic)
8871 {
8872         int size, offset ;
8873         sym_link *retype = getSpec(operandType(result));
8874         
8875         FENTRY;
8876         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8877         aopOp(left,ic,FALSE);
8878         aopOp(result,ic,FALSE);
8879         
8880         
8881         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8882         
8883         /* if the operand is already in dptr 
8884         then we do nothing else we move the value to dptr */
8885         //  if (AOP_TYPE(left) != AOP_STR) {
8886         /* if this is remateriazable */
8887         if (AOP_TYPE(left) == AOP_IMMD) {
8888                 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8889                 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8890         }
8891         else { /* we need to get it byte by byte */
8892                 
8893                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8894                 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8895                 
8896                 size = AOP_SIZE(result);
8897                 offset = 0 ;
8898                 
8899                 while(size--) {
8900                         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8901                         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8902                         if(size)
8903                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8904                 }
8905                 goto release;
8906         }
8907         //}
8908         /* so dptr know contains the address */
8909         
8910         /* if bit then unpack */
8911         //if (IS_BITFIELD(retype)) 
8912         //  genUnpackBits(result,"dptr",GPOINTER);
8913         
8914 release:
8915         freeAsmop(left,NULL,ic,TRUE);
8916         freeAsmop(result,NULL,ic,TRUE);
8917         
8918 }
8919
8920 /*-----------------------------------------------------------------*/
8921 /* genConstPointerGet - get value from const generic pointer space */
8922 /*-----------------------------------------------------------------*/
8923 static void genConstPointerGet (operand *left,
8924                                                                 operand *result, iCode *ic)
8925 {
8926         //sym_link *retype = getSpec(operandType(result));
8927         symbol *albl, *blbl;//, *clbl;
8928         PIC_OPCODE poc;
8929         int i, size, lit;
8930         pCodeOp *pcop;
8931         
8932         FENTRY;
8933         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8934         aopOp(left,ic,FALSE);
8935         aopOp(result,ic,FALSE);
8936         
8937         size = AOP_SIZE(result);
8938         
8939         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8940         
8941         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8942
8943         lit = aop_isLitLike (AOP(left));
8944         poc = lit ? POC_MOVLW : POC_MOVFW;
8945
8946         if (lit)
8947         {
8948                 for (i = 0; i < size; i++)
8949                 {
8950                         albl = newiTempLabel(NULL);
8951                         blbl = newiTempLabel(NULL);
8952                         
8953                         emitpcode(POC_CALL,popGetLabel(albl->key));
8954                         pcop = popGetLabel(blbl->key);
8955                         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8956                         emitpcode(POC_GOTO,pcop);
8957                         
8958                         emitpLabel(albl->key);
8959                         emitpcode(poc,popGetAddr(AOP(left),1,i));
8960                         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8961                         emitpcode(poc,popGetAddr(AOP(left),0,i));
8962                         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8963                 
8964                         emitpLabel(blbl->key);
8965                         emitpcode(POC_MOVWF,popGet(AOP(result),i));
8966                 } // for
8967         } else {
8968                 albl = newiTempLabel(NULL);
8969                 blbl = newiTempLabel(NULL);
8970                 //clbl = newiTempLabel(NULL);
8971
8972                 emitpcode (POC_GOTO, popGetLabel (blbl->key));
8973                 
8974                 emitpLabel(albl->key);
8975                 emitpcode(poc,popGet(AOP(left),1));
8976                 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8977                 emitpcode(poc,popGet(AOP(left),0));
8978                 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8979                 
8980                 emitpLabel(blbl->key);
8981                 
8982                 for (i = 0; i < size; i++)
8983                 {
8984                         emitpcode(POC_CALL,popGetLabel(albl->key));
8985                         /* the next two instructions (plus clbl) might be useless... */
8986                         //pcop = popGetLabel(clbl->key);
8987                         //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8988                         //emitpcode(POC_GOTO,pcop);
8989                         //emitpLabel(clbl->key);
8990
8991                         if (i+1 < size) {
8992                                 emitpcode (POC_INCF, popGet (AOP(left), 0));
8993                                 emitSKPNZ;
8994                                 emitpcode (POC_INCF, popGet (AOP(left), 1));
8995                         }
8996                         emitpcode(POC_MOVWF,popGet(AOP(result),i));
8997                 } // for
8998                 if (size > 1) {
8999                         /* restore left's value */
9000                         emitpcode (POC_MOVLW, popGetLit (size-1));
9001                         emitpcode (POC_SUBWF, popGet (AOP(left), 0));
9002                         emitSKPC;
9003                         emitpcode (POC_DECF, popGet (AOP(left), 1));
9004                 } // if
9005         } // if (lit)
9006         
9007         freeAsmop(left,NULL,ic,TRUE);
9008         freeAsmop(result,NULL,ic,TRUE);
9009         
9010 }
9011 /*-----------------------------------------------------------------*/
9012 /* genPointerGet - generate code for pointer get                   */
9013 /*-----------------------------------------------------------------*/
9014 static void genPointerGet (iCode *ic)
9015 {
9016         operand *left, *result ;
9017         sym_link *type, *etype;
9018         int p_type = -1;
9019         
9020         FENTRY;
9021         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9022         
9023         left = IC_LEFT(ic);
9024         result = IC_RESULT(ic) ;
9025         
9026         /* depending on the type of pointer we need to
9027         move it to the correct pointer register */
9028         type = operandType(left);
9029         etype = getSpec(type);
9030         
9031         if (IS_PTR_CONST(type))
9032                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9033         
9034         /* if left is of type of pointer then it is simple */
9035         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9036                 p_type = DCL_TYPE(type);
9037         else {
9038                 /* we have to go by the storage class */
9039                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9040                 
9041                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9042                 
9043                 if (SPEC_OCLS(etype)->codesp ) {
9044                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9045                         //p_type = CPOINTER ; 
9046                 }
9047                 else
9048                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9049                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9050                         /*p_type = FPOINTER ;*/ 
9051                         else
9052                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9053                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9054                                 /*        p_type = PPOINTER; */
9055                                 else
9056                                         if (SPEC_OCLS(etype) == idata )
9057                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9058                                         /*      p_type = IPOINTER; */
9059                                         else
9060                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9061                                         /*      p_type = POINTER ; */
9062         }
9063         
9064         /* now that we have the pointer type we assign
9065         the pointer values */
9066         switch (p_type) {
9067                 
9068         case POINTER: 
9069         case IPOINTER:
9070                 genNearPointerGet (left,result,ic);
9071                 break;
9072                 
9073         case PPOINTER:
9074                 genPagedPointerGet(left,result,ic);
9075                 break;
9076                 
9077         case FPOINTER:
9078                 genFarPointerGet (left,result,ic);
9079                 break;
9080                 
9081         case CPOINTER:
9082                 genConstPointerGet (left,result,ic);
9083                 //pic14_emitcodePointerGet (left,result,ic);
9084                 break;
9085                 
9086         case GPOINTER:
9087                 if (IS_CODEPTR(type) || IS_PTR_CONST(type) || SPEC_CONST(etype))
9088                         genConstPointerGet (left,result,ic);
9089                 else
9090                         genGenPointerGet (left,result,ic);
9091                 break;
9092         default:
9093                 assert ( !"unhandled pointer type" );
9094                 break;
9095         }
9096         
9097 }
9098
9099 /*-----------------------------------------------------------------*/
9100 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into  */
9101 /* A through a pointer register (R0, R1, or DPTR). The original    */
9102 /* value of A can be preserved in B.                               */
9103 /* PIC has to use INDF register.                                   */
9104 /*-----------------------------------------------------------------*/
9105 static void
9106 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9107 {
9108     FENTRY;
9109     switch (p_type)
9110     {
9111     case IPOINTER:
9112     case POINTER:
9113                 if (preserveAinB)
9114                         pic14_emitcode ("mov", "b,a");
9115 //              pic14_emitcode ("mov", "a,@%s", rname);
9116                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
9117                 break;
9118                 
9119     case PPOINTER:
9120                 if (preserveAinB)
9121                         pic14_emitcode ("mov", "b,a");
9122                 pic14_emitcode ("movx", "a,@%s", rname);
9123                 break;
9124                 
9125     case FPOINTER:
9126                 if (preserveAinB)
9127                         pic14_emitcode ("mov", "b,a");
9128                 pic14_emitcode ("movx", "a,@dptr");
9129                 break;
9130                 
9131     case CPOINTER:
9132                 if (preserveAinB)
9133                         pic14_emitcode ("mov", "b,a");
9134                 pic14_emitcode ("clr", "a");
9135                 pic14_emitcode ("movc", "a,@a+dptr");
9136                 break;
9137                 
9138     case GPOINTER:
9139                 if (preserveAinB)
9140         {
9141                         pic14_emitcode ("push", "b");
9142                         pic14_emitcode ("push", "acc");
9143         }
9144                 pic14_emitcode ("lcall", "__gptrget");
9145                 if (preserveAinB)
9146                         pic14_emitcode ("pop", "b");
9147                 break;
9148     }
9149 }
9150
9151 /*-----------------------------------------------------------------*/
9152 /* emitPtrByteSet - emits code to set a byte from src through a    */
9153 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
9154 /*-----------------------------------------------------------------*/
9155 static void
9156 emitPtrByteSet (char *rname, int p_type, char *src)
9157 {
9158     FENTRY;
9159     switch (p_type)
9160     {
9161     case IPOINTER:
9162     case POINTER:
9163                 if (*src=='@')
9164         {
9165                         MOVA (src);
9166                         pic14_emitcode ("mov", "@%s,a", rname);
9167         }
9168                 else
9169 //                      pic14_emitcode ("mov", "@%s,%s", rname, src);
9170                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9171                 break;
9172                 
9173     case PPOINTER:
9174                 MOVA (src);
9175                 pic14_emitcode ("movx", "@%s,a", rname);
9176                 break;
9177                 
9178     case FPOINTER:
9179                 MOVA (src);
9180                 pic14_emitcode ("movx", "@dptr,a");
9181                 break;
9182                 
9183     case GPOINTER:
9184                 MOVA (src);
9185                 pic14_emitcode ("lcall", "__gptrput");
9186                 break;
9187     }
9188 }
9189
9190 /*-----------------------------------------------------------------*/
9191 /* genPackBits - generates code for packed bit storage             */
9192 /*-----------------------------------------------------------------*/
9193 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
9194 {
9195         int offset = 0;       /* source byte offset */
9196         int rlen = 0;         /* remaining bitfield length */
9197         int blen;             /* bitfield length */
9198         int bstr;             /* bitfield starting bit within byte */
9199         int litval;           /* source literal value (if AOP_LIT) */
9200         unsigned char mask;   /* bitmask within current byte */
9201
9202         FENTRY;
9203         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9204         
9205         blen = SPEC_BLEN (etype);
9206         bstr = SPEC_BSTR (etype);
9207         
9208         /* If the bitfield length is less than a byte */
9209         if (blen < 8)
9210     {
9211                 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9212                         (unsigned char) (0xFF >> (8 - bstr)));
9213                 
9214                 if (AOP_TYPE (right) == AOP_LIT)
9215         {
9216                         /* Case with a bitfield length <8 and literal source
9217                         */
9218                         int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9219                         if (blen == 1) {
9220                                 if (p_type == -1) {
9221                                         pCodeOp *pcop;
9222                                         if (AOP(result)->type == AOP_PCODE)
9223                                                 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9224                                         else
9225                                                 pcop = popGet(AOP(result),0);
9226                                         emitpcode(lit?POC_BSF:POC_BCF,pcop);
9227                                 } else {
9228                                         emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
9229                                 }
9230                                 return;
9231                         } else {
9232                                 litval = lit << bstr;
9233                                 litval &= (~mask) & 0xff;
9234                                 if (p_type == -1)
9235                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9236                                 else
9237                                         emitPtrByteGet (rname, p_type, FALSE);
9238                                 if ((mask|litval)!=0xff)
9239                                         emitpcode(POC_ANDLW,popGetLit(mask));
9240                                 if (litval)
9241                                         emitpcode(POC_IORLW,popGetLit(litval));
9242                         }
9243         }
9244                 else
9245         {
9246                         if (blen==1) {
9247                                 if (p_type == -1) {
9248                                         /* 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 */
9249                                         emitpcode(POC_RLF,popGet(AOP(right),0));
9250                                         emitSKPC;
9251                                         emitpcode(POC_BCF,popGet(AOP(result),0));
9252                                         emitSKPNC;
9253                                         emitpcode(POC_BSF,popGet(AOP(result),0));
9254                                 } else if (p_type!=GPOINTER) {
9255                                         /* Case with a bitfield length == 1 and no generic pointer
9256                                         */
9257                                         if (AOP_TYPE (right) == AOP_CRY)
9258                                                 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9259                                         else
9260                                         {
9261                                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9262                                                 pic14_emitcode ("rrc","a");
9263                                         }
9264                                         emitPtrByteGet (rname, p_type, FALSE);
9265                                         pic14_emitcode ("mov","acc.%d,c",bstr);
9266                                 }
9267             }
9268                         else
9269             {
9270                                 //bool pushedB;
9271                                 /* Case with a bitfield length < 8 and arbitrary source
9272                                 */
9273                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9274                                 /* shift and mask source value */
9275                                 AccLsh (right,0,bstr);
9276                                 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9277                                 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
9278                                 
9279                                 //pushedB = pushB ();
9280                                 if (p_type == -1)
9281                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9282                                 else
9283                                         emitPtrByteGet (rname, p_type, TRUE);
9284                                 
9285                                 pic14_emitcode ("anl", "a,#0x%02x", mask);
9286                                 pic14_emitcode ("orl", "a,b");
9287                                 emitpcode(POC_ANDLW,popGetLit(mask));
9288                                 emitpcode(POC_IORFW,popGet(AOP(right),0));
9289                                 if (p_type == GPOINTER)
9290                                         pic14_emitcode ("pop", "b");
9291                                 
9292                                 //popB (pushedB);
9293                         }
9294         }
9295                 
9296                 if (p_type == -1)
9297                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9298                 else
9299                         emitPtrByteSet (rname, p_type, "a");
9300                 return;
9301     }
9302         
9303         /* Bit length is greater than 7 bits. In this case, copy  */
9304         /* all except the partial byte at the end                 */
9305         for (rlen=blen;rlen>=8;rlen-=8)
9306     {
9307                 emitPtrByteSet (rname, p_type,
9308                         aopGet (AOP (right), offset++, FALSE, TRUE) );
9309                 if (rlen>8)
9310                         pic14_emitcode ("inc", "%s", rname);
9311     }
9312         
9313         /* If there was a partial byte at the end */
9314         if (rlen)
9315     {
9316                 mask = (((unsigned char) -1 << rlen) & 0xff);
9317                 
9318                 if (AOP_TYPE (right) == AOP_LIT)
9319         {
9320                 /* Case with partial byte and literal source
9321                         */
9322                         litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9323                         litval >>= (blen-rlen);
9324                         litval &= (~mask) & 0xff;
9325                         emitPtrByteGet (rname, p_type, FALSE);
9326                         if ((mask|litval)!=0xff)
9327                                 pic14_emitcode ("anl","a,#0x%02x", mask);
9328                         if (litval)
9329                                 pic14_emitcode ("orl","a,#0x%02x", litval);
9330         }
9331                 else
9332         {
9333                         //bool pushedB;
9334                         /* Case with partial byte and arbitrary source
9335                         */
9336                         MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9337                         pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9338                         
9339                         //pushedB = pushB ();
9340                         /* transfer A to B and get next byte */
9341                         emitPtrByteGet (rname, p_type, TRUE);
9342                         
9343                         pic14_emitcode ("anl", "a,#0x%02x", mask);
9344                         pic14_emitcode ("orl", "a,b");
9345                         if (p_type == GPOINTER)
9346                                 pic14_emitcode ("pop", "b");
9347                         
9348                         //popB (pushedB);
9349         }
9350                 emitPtrByteSet (rname, p_type, "a");
9351     }
9352         
9353 }
9354
9355 /*-----------------------------------------------------------------*/
9356 /* SetIrp - Set IRP bit                                            */
9357 /*-----------------------------------------------------------------*/
9358 void SetIrp(operand *result) {
9359         FENTRY;
9360         if (AOP_TYPE(result) == AOP_LIT) {
9361                 unsigned lit = (unsigned)operandLitValue(result);
9362                 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9363         } else {
9364                 if (PCOP(AOP(result))->type == PO_LITERAL) {
9365                         int addrs = PCOL(AOP(result))->lit;
9366                         emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9367                 } else {
9368                         emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
9369                         if(AOP_SIZE(result) > 1) {
9370                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9371                                 emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9372                         }
9373                 }
9374         }
9375 }
9376
9377 /*-----------------------------------------------------------------*/
9378 /* genDataPointerSet - remat pointer to data space                 */
9379 /*-----------------------------------------------------------------*/
9380 static void genDataPointerSet(operand *right,
9381         operand *result,
9382         iCode *ic)
9383 {
9384         int size, offset = 0 ;
9385         
9386         FENTRY;
9387         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9388         aopOp(right,ic,FALSE);
9389         aopOp(result,ic,FALSE);
9390         
9391         size = AOP_SIZE(right);
9392         /*
9393         if ( AOP_TYPE(result) == AOP_PCODE) {
9394         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9395         AOP(result)->aopu.pcop->name,
9396         PCOI(AOP(result)->aopu.pcop)->offset);
9397         }
9398         */
9399         
9400         // tsd, was l+1 - the underline `_' prefix was being stripped
9401         while (size--) {
9402                 emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
9403                 
9404                 if (AOP_TYPE(right) == AOP_LIT) {
9405                         unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9406                         lit = lit >> (8*offset);
9407                         if(lit&0xff) {
9408                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9409                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9410                         } else {
9411                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9412                         }
9413                 } else {
9414                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9415                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9416                 }
9417                 
9418                 offset++;
9419         }
9420         
9421         freeAsmop(right,NULL,ic,TRUE);
9422         freeAsmop(result,NULL,ic,TRUE);
9423 }
9424
9425 /*-----------------------------------------------------------------*/
9426 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9427 /*-----------------------------------------------------------------*/
9428 static void genNearPointerSet (operand *right,
9429                                                            operand *result, 
9430                                                            iCode *ic)
9431 {
9432         asmop *aop = NULL;
9433         sym_link *ptype = operandType(result);
9434         sym_link *retype = getSpec(operandType(right));
9435         sym_link *letype = getSpec(ptype);
9436         int direct = 0;
9437         
9438         
9439         FENTRY;
9440         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9441         aopOp(result,ic,FALSE);
9442         
9443         
9444         /* if the result is rematerializable &
9445         in data space & not a bit variable */
9446         //if (AOP_TYPE(result) == AOP_IMMD &&
9447         if (AOP_TYPE(result) == AOP_PCODE &&
9448                 DCL_TYPE(ptype) == POINTER   &&
9449                 !IS_BITVAR (retype) &&
9450                 !IS_BITVAR (letype)) {
9451                 genDataPointerSet (right,result,ic);
9452                 freeAsmop(result,NULL,ic,TRUE);
9453                 return;
9454         }
9455
9456         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9457         aopOp(right,ic,FALSE);
9458         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9459         
9460         /* Check if can access directly instead of via a pointer */
9461         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9462                 direct = 1;
9463         }
9464
9465         /* If the pointer value is not in a the FSR then need to put it in */
9466         if (!AOP_INPREG(AOP(result)) && !direct) {
9467                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9468                 if (PCOP(AOP(result))->type == PO_LITERAL) 
9469                         emitpcode(POC_MOVLW, popGet(AOP(result),0));
9470                 else
9471                         emitpcode(POC_MOVFW, popGet(AOP(result),0));
9472                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
9473         }
9474
9475         /* Must set/reset IRP bit for use with FSR. */
9476         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9477         if (!direct)
9478                 SetIrp(result);
9479
9480         /* if bitfield then unpack the bits */
9481         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9482                 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
9483         } else {
9484                 /* we have can just get the values */
9485                 int size = AOP_SIZE(right);
9486                 int offset = 0 ;    
9487                 
9488                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9489                 while (size--) {
9490                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9491                         if (*l == '@' ) {
9492                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9493                         } else {
9494                                 if (AOP_TYPE(right) == AOP_LIT) {
9495                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9496                                 } else {
9497                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9498                                 }
9499                                 if (direct)
9500                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9501                                 else
9502                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9503                         }
9504                         if (size && !direct)
9505                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9506                         offset++;
9507                 }
9508         }
9509         
9510         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9511         /* now some housekeeping stuff */
9512         if (aop) {
9513                 /* we had to allocate for this iCode */
9514                 freeAsmop(NULL,aop,ic,TRUE);
9515         } else { 
9516                 /* we did not allocate which means left
9517                 already in a pointer register, then
9518                 if size > 0 && this could be used again
9519                 we have to point it back to where it 
9520                 belongs */
9521                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9522                 if (AOP_SIZE(right) > 1 &&
9523                         !OP_SYMBOL(result)->remat &&
9524                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9525                         ic->depth )) {
9526                         int size = AOP_SIZE(right) - 1;
9527                         while (size--)
9528                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9529                 }
9530         }
9531         
9532         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9533         /* done */
9534
9535         freeAsmop(right,NULL,ic,TRUE);
9536         freeAsmop(result,NULL,ic,TRUE);
9537 }
9538
9539 /*-----------------------------------------------------------------*/
9540 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9541 /*-----------------------------------------------------------------*/
9542 static void genPagedPointerSet (operand *right,
9543                                                                 operand *result, 
9544                                                                 iCode *ic)
9545 {
9546         asmop *aop = NULL;
9547         regs *preg = NULL ;
9548         char *rname , *l;
9549         sym_link *retype;
9550         
9551         FENTRY;
9552         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9553         
9554         retype= getSpec(operandType(right));
9555         
9556         aopOp(result,ic,FALSE);
9557         
9558         /* if the value is already in a pointer register
9559         then don't need anything more */
9560         if (!AOP_INPREG(AOP(result))) {
9561                 /* otherwise get a free pointer register */
9562                 aop = newAsmop(0);
9563                 preg = getFreePtr(ic,&aop,FALSE);
9564                 pic14_emitcode("mov","%s,%s",
9565                         preg->name,
9566                         aopGet(AOP(result),0,FALSE,TRUE));
9567                 rname = preg->name ;
9568         } else
9569                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9570         
9571         freeAsmop(result,NULL,ic,TRUE);
9572         aopOp (right,ic,FALSE);
9573         
9574         /* if bitfield then unpack the bits */
9575         if (IS_BITFIELD(retype)) 
9576                 genPackBits (retype,result,right,rname,PPOINTER);
9577         else {
9578                 /* we have can just get the values */
9579                 int size = AOP_SIZE(right);
9580                 int offset = 0 ;  
9581                 
9582                 while (size--) {
9583                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9584                         
9585                         MOVA(l);
9586                         pic14_emitcode("movx","@%s,a",rname);
9587                         
9588                         if (size)
9589                                 pic14_emitcode("inc","%s",rname);
9590                         
9591                         offset++;
9592                 }
9593         }
9594         
9595         /* now some housekeeping stuff */
9596         if (aop) {
9597                 /* we had to allocate for this iCode */
9598                 freeAsmop(NULL,aop,ic,TRUE);
9599         } else { 
9600         /* we did not allocate which means left
9601         already in a pointer register, then
9602         if size > 0 && this could be used again
9603         we have to point it back to where it 
9604                 belongs */
9605                 if (AOP_SIZE(right) > 1 &&
9606                         !OP_SYMBOL(result)->remat &&
9607                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9608                         ic->depth )) {
9609                         int size = AOP_SIZE(right) - 1;
9610                         while (size--)
9611                                 pic14_emitcode("dec","%s",rname);
9612                 }
9613         }
9614         
9615         /* done */
9616         freeAsmop(right,NULL,ic,TRUE);
9617         
9618         
9619 }
9620
9621 /*-----------------------------------------------------------------*/
9622 /* genFarPointerSet - set value from far space                     */
9623 /*-----------------------------------------------------------------*/
9624 static void genFarPointerSet (operand *right,
9625                                                           operand *result, iCode *ic)
9626 {
9627         int size, offset ;
9628         sym_link *retype = getSpec(operandType(right));
9629         
9630         FENTRY;
9631         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9632         aopOp(result,ic,FALSE);
9633         
9634         /* if the operand is already in dptr 
9635         then we do nothing else we move the value to dptr */
9636         if (AOP_TYPE(result) != AOP_STR) {
9637                 /* if this is remateriazable */
9638                 if (AOP_TYPE(result) == AOP_IMMD)
9639                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9640                 else { /* we need to get it byte by byte */
9641                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9642                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9643                         if (options.model == MODEL_FLAT24)
9644                         {
9645                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9646                         }
9647                 }
9648         }
9649         /* so dptr know contains the address */
9650         freeAsmop(result,NULL,ic,TRUE);
9651         aopOp(right,ic,FALSE);
9652         
9653         /* if bit then unpack */
9654         if (IS_BITFIELD(retype)) 
9655                 genPackBits(retype,result,right,"dptr",FPOINTER);
9656         else {
9657                 size = AOP_SIZE(right);
9658                 offset = 0 ;
9659                 
9660                 while (size--) {
9661                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9662                         MOVA(l);
9663                         pic14_emitcode("movx","@dptr,a");
9664                         if (size)
9665                                 pic14_emitcode("inc","dptr");
9666                 }
9667         }
9668         
9669         freeAsmop(right,NULL,ic,TRUE);
9670 }
9671
9672 /*-----------------------------------------------------------------*/
9673 /* genGenPointerSet - set value from generic pointer space         */
9674 /*-----------------------------------------------------------------*/
9675 static void genGenPointerSet (operand *right,
9676                                                           operand *result, iCode *ic)
9677 {
9678         sym_link *ptype = operandType(result);
9679         sym_link *retype = getSpec(operandType(right));
9680         sym_link *letype = getSpec (ptype);
9681         
9682         FENTRY;
9683         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9684         
9685         aopOp(result,ic,FALSE);
9686         aopOp(right,ic,FALSE);
9687         
9688         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9689         
9690         /* if the operand is already in dptr 
9691         then we do nothing else we move the value to dptr */
9692         if (AOP_TYPE(result) != AOP_STR) {
9693                 /* if this is remateriazable */
9694                 if (AOP_TYPE(result) == AOP_IMMD) {
9695                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9696                         pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9697                 }
9698                 else {
9699                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9700                         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9701
9702                         /* Must set/reset IRP bit for use with FSR. */
9703                         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9704                         SetIrp(result);
9705                 }
9706         }
9707
9708         /* if bitfield then unpack the bits */
9709         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9710                 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9711         } else {
9712                 /* we have can just get the values */
9713                 int size = AOP_SIZE(right);
9714                 int offset = 0 ;    
9715                 
9716                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9717                 while (size--) {
9718                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9719                         if (*l == '@' ) {
9720                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9721                         } else {
9722                                 if (AOP_TYPE(right) == AOP_LIT) {
9723                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9724                                 } else {
9725                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9726                                 }
9727                                 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9728                         }
9729                         if (size)
9730                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9731                         offset++;
9732                 }
9733         }
9734         
9735         freeAsmop(right,NULL,ic,TRUE);
9736         freeAsmop(result,NULL,ic,TRUE);
9737 }
9738
9739 /*-----------------------------------------------------------------*/
9740 /* genPointerSet - stores the value into a pointer location        */
9741 /*-----------------------------------------------------------------*/
9742 static void genPointerSet (iCode *ic)
9743 {    
9744         operand *right, *result ;
9745         sym_link *type, *etype;
9746         int p_type;
9747         
9748         FENTRY;
9749         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9750         
9751         right = IC_RIGHT(ic);
9752         result = IC_RESULT(ic) ;
9753         
9754         /* depending on the type of pointer we need to
9755         move it to the correct pointer register */
9756         type = operandType(result);
9757         etype = getSpec(type);
9758         /* if left is of type of pointer then it is simple */
9759         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9760                 p_type = DCL_TYPE(type);
9761         }
9762         else {
9763                 /* we have to go by the storage class */
9764                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9765                 
9766                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9767                 /*      p_type = CPOINTER ;  */
9768                 /*  } */
9769                 /*  else */
9770                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9771                 /*    p_type = FPOINTER ; */
9772                 /*      else */
9773                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9774                 /*        p_type = PPOINTER ; */
9775                 /*    else */
9776                 /*        if (SPEC_OCLS(etype) == idata ) */
9777                 /*      p_type = IPOINTER ; */
9778                 /*        else */
9779                 /*      p_type = POINTER ; */
9780         }
9781         
9782         /* now that we have the pointer type we assign
9783         the pointer values */
9784         switch (p_type) {
9785                 
9786         case POINTER:
9787         case IPOINTER:
9788                 genNearPointerSet (right,result,ic);
9789                 break;
9790                 
9791         case PPOINTER:
9792                 genPagedPointerSet (right,result,ic);
9793                 break;
9794                 
9795         case FPOINTER:
9796                 genFarPointerSet (right,result,ic);
9797                 break;
9798                 
9799         case GPOINTER:
9800                 genGenPointerSet (right,result,ic);
9801                 break;
9802                 
9803         default:
9804                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9805                         "genPointerSet: illegal pointer type");
9806         }
9807 }
9808
9809 /*-----------------------------------------------------------------*/
9810 /* genIfx - generate code for Ifx statement                        */
9811 /*-----------------------------------------------------------------*/
9812 static void genIfx (iCode *ic, iCode *popIc)
9813 {
9814         operand *cond = IC_COND(ic);
9815         int isbit =0;
9816         
9817         FENTRY;
9818         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9819         
9820         aopOp(cond,ic,FALSE);
9821         
9822         /* get the value into acc */
9823         if (AOP_TYPE(cond) != AOP_CRY)
9824                 pic14_toBoolean(cond);
9825         else
9826                 isbit = 1;
9827         /* the result is now in the accumulator */
9828         freeAsmop(cond,NULL,ic,TRUE);
9829         
9830         /* if there was something to be popped then do it */
9831         if (popIc)
9832                 genIpop(popIc);
9833         
9834         /* if the condition is  a bit variable */
9835         if (isbit && IS_ITEMP(cond) && 
9836                 SPIL_LOC(cond)) {
9837                 genIfxJump(ic,SPIL_LOC(cond)->rname);
9838                 DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9839         }
9840         else {
9841                 if (isbit && !IS_ITEMP(cond))
9842                         genIfxJump(ic,OP_SYMBOL(cond)->rname);
9843                 else
9844                         genIfxJump(ic,"a");
9845         }
9846         ic->generated = 1;
9847         
9848 }
9849
9850 /*-----------------------------------------------------------------*/
9851 /* genAddrOf - generates code for address of                       */
9852 /*-----------------------------------------------------------------*/
9853 static void genAddrOf (iCode *ic)
9854 {
9855         operand *right, *result, *left;
9856         int size, offset ;
9857         
9858         FENTRY;
9859         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9860         
9861         
9862         //aopOp(IC_RESULT(ic),ic,FALSE);
9863         
9864         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9865         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9866         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9867         
9868         DEBUGpic14_AopType(__LINE__,left,right,result);
9869         assert (IS_SYMOP (left));
9870         
9871         /* sanity check: generic pointers to code space are not yet supported,
9872          * pionters to codespace must not be assigned addresses of __data values. */
9873  #if 0
9874         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9875         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)));
9876         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)));
9877         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)));
9878         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)));
9879 #endif
9880
9881         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9882           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9883                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9884                 OP_SYMBOL(left)->name);
9885         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9886           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9887                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9888                 OP_SYMBOL(left)->name);
9889         }
9890         
9891         size = AOP_SIZE(IC_RESULT(ic));
9892         offset = 0;
9893         
9894         while (size--) {
9895                 /* fixing bug #863624, reported from (errolv) */
9896                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9897                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9898                 
9899 #if 0
9900                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9901                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9902 #endif
9903                 offset++;
9904         }
9905         
9906         freeAsmop(left,NULL,ic,FALSE);
9907         freeAsmop(result,NULL,ic,TRUE);
9908         
9909 }
9910
9911 #if 0
9912 /*-----------------------------------------------------------------*/
9913 /* genFarFarAssign - assignment when both are in far space         */
9914 /*-----------------------------------------------------------------*/
9915 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9916 {
9917         int size = AOP_SIZE(right);
9918         int offset = 0;
9919         char *l ;
9920         /* first push the right side on to the stack */
9921         while (size--) {
9922                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9923                 MOVA(l);
9924                 pic14_emitcode ("push","acc");
9925         }
9926         
9927         freeAsmop(right,NULL,ic,FALSE);
9928         /* now assign DPTR to result */
9929         aopOp(result,ic,FALSE);
9930         size = AOP_SIZE(result);
9931         while (size--) {
9932                 pic14_emitcode ("pop","acc");
9933                 aopPut(AOP(result),"a",--offset);
9934         }
9935         freeAsmop(result,NULL,ic,FALSE);
9936         
9937 }
9938 #endif
9939
9940 /*-----------------------------------------------------------------*/
9941 /* genAssign - generate code for assignment                        */
9942 /*-----------------------------------------------------------------*/
9943 static void genAssign (iCode *ic)
9944 {
9945         operand *result, *right;
9946         int size, offset,know_W;
9947         unsigned long lit = 0L;
9948         
9949         result = IC_RESULT(ic);
9950         right  = IC_RIGHT(ic) ;
9951         
9952         FENTRY;
9953         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9954         
9955         /* if they are the same */
9956         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9957                 return ;
9958         
9959         aopOp(right,ic,FALSE);
9960         aopOp(result,ic,TRUE);
9961         
9962         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9963         
9964         /* if they are the same registers */
9965         if (pic14_sameRegs(AOP(right),AOP(result)))
9966                 goto release;
9967
9968         /* special case: assign from __code */
9969         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
9970                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
9971                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
9972                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
9973                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
9974         {
9975           emitpComment ("genAssign from CODESPACE");
9976           genConstPointerGet (right, result, ic);
9977           goto release;
9978         }
9979         
9980         /* just for symmetry reasons... */
9981         if (!IS_ITEMP(result)
9982                 && IS_SYMOP (result)
9983                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
9984         {
9985           assert ( !"cannot write to CODESPACE" );
9986         }
9987
9988         /* if the result is a bit */
9989         if (AOP_TYPE(result) == AOP_CRY) {
9990                 
9991         /* if the right size is a literal then
9992                 we know what the value is */
9993                 if (AOP_TYPE(right) == AOP_LIT) {
9994                         
9995                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9996                                 popGet(AOP(result),0));
9997                         
9998                         if (((int) operandLitValue(right))) 
9999                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10000                                 AOP(result)->aopu.aop_dir,
10001                                 AOP(result)->aopu.aop_dir);
10002                         else
10003                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10004                                 AOP(result)->aopu.aop_dir,
10005                                 AOP(result)->aopu.aop_dir);
10006                         goto release;
10007                 }
10008                 
10009                 /* the right is also a bit variable */
10010                 if (AOP_TYPE(right) == AOP_CRY) {
10011                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10012                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10013                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10014                         
10015                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10016                                 AOP(result)->aopu.aop_dir,
10017                                 AOP(result)->aopu.aop_dir);
10018                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10019                                 AOP(right)->aopu.aop_dir,
10020                                 AOP(right)->aopu.aop_dir);
10021                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10022                                 AOP(result)->aopu.aop_dir,
10023                                 AOP(result)->aopu.aop_dir);
10024                         goto release ;
10025                 }
10026                 
10027                 /* we need to or */
10028                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10029                 pic14_toBoolean(right);
10030                 emitSKPZ;
10031                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10032                 //aopPut(AOP(result),"a",0);
10033                 goto release ;
10034         }
10035         
10036         /* bit variables done */
10037         /* general case */
10038         size = AOP_SIZE(result);
10039         offset = 0 ;
10040         if(AOP_TYPE(right) == AOP_LIT)
10041                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10042         
10043         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10044                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10045                 if(aopIdx(AOP(result),0) == 4) {
10046                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10047                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10048                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10049                         goto release;
10050                 } else
10051                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10052         }
10053         
10054         know_W=-1;
10055         while (size--) {
10056                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10057                 if(AOP_TYPE(right) == AOP_LIT) {
10058                         if(lit&0xff) {
10059                                 if(know_W != (int)(lit&0xff))
10060                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10061                                 know_W = lit&0xff;
10062                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10063                         } else
10064                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10065                         
10066                         lit >>= 8;
10067                         
10068                 } else if (AOP_TYPE(right) == AOP_CRY) {
10069                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10070                         if(offset == 0) {
10071                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10072                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10073                         }
10074                 } else {
10075                         mov2w (AOP(right), offset);
10076                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10077                 }
10078                 
10079                 offset++;
10080         }
10081         
10082         
10083 release:
10084         freeAsmop (right,NULL,ic,FALSE);
10085         freeAsmop (result,NULL,ic,TRUE);
10086 }   
10087
10088 /*-----------------------------------------------------------------*/
10089 /* genJumpTab - genrates code for jump table                       */
10090 /*-----------------------------------------------------------------*/
10091 static void genJumpTab (iCode *ic)
10092 {
10093         symbol *jtab;
10094         char *l;
10095         
10096         FENTRY;
10097         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10098         
10099         aopOp(IC_JTCOND(ic),ic,FALSE);
10100         /* get the condition into accumulator */
10101         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10102         MOVA(l);
10103         /* multiply by three */
10104         pic14_emitcode("add","a,acc");
10105         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10106         
10107         jtab = newiTempLabel(NULL);
10108         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10109         pic14_emitcode("jmp","@a+dptr");
10110         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10111         
10112         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10113         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10114         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10115         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10116         emitSKPNC;
10117         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10118         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10119         emitpLabel(jtab->key);
10120         
10121         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10122         
10123         /* now generate the jump labels */
10124         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10125         jtab = setNextItem(IC_JTLABELS(ic))) {
10126                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10127                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10128                 
10129         }
10130         
10131 }
10132
10133 /*-----------------------------------------------------------------*/
10134 /* genMixedOperation - gen code for operators between mixed types  */
10135 /*-----------------------------------------------------------------*/
10136 /*
10137 TSD - Written for the PIC port - but this unfortunately is buggy.
10138 This routine is good in that it is able to efficiently promote 
10139 types to different (larger) sizes. Unfortunately, the temporary
10140 variables that are optimized out by this routine are sometimes
10141 used in other places. So until I know how to really parse the 
10142 iCode tree, I'm going to not be using this routine :(.
10143 */
10144 static int genMixedOperation (iCode *ic)
10145 {
10146         FENTRY;
10147 #if 0
10148         operand *result = IC_RESULT(ic);
10149         sym_link *ctype = operandType(IC_LEFT(ic));
10150         operand *right = IC_RIGHT(ic);
10151         int ret = 0;
10152         int big,small;
10153         int offset;
10154         
10155         iCode *nextic;
10156         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10157         
10158         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10159         
10160         nextic = ic->next;
10161         if(!nextic)
10162                 return 0;
10163         
10164         nextright = IC_RIGHT(nextic);
10165         nextleft  = IC_LEFT(nextic);
10166         nextresult = IC_RESULT(nextic);
10167         
10168         aopOp(right,ic,FALSE);
10169         aopOp(result,ic,FALSE);
10170         aopOp(nextright,  nextic, FALSE);
10171         aopOp(nextleft,   nextic, FALSE);
10172         aopOp(nextresult, nextic, FALSE);
10173         
10174         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10175                 
10176                 operand *t = right;
10177                 right = nextright;
10178                 nextright = t; 
10179                 
10180                 pic14_emitcode(";remove right +","");
10181                 
10182         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10183         /*
10184         operand *t = right;
10185         right = nextleft;
10186         nextleft = t; 
10187                 */
10188                 pic14_emitcode(";remove left +","");
10189         } else
10190                 return 0;
10191         
10192         big = AOP_SIZE(nextleft);
10193         small = AOP_SIZE(nextright);
10194         
10195         switch(nextic->op) {
10196                 
10197         case '+':
10198                 pic14_emitcode(";optimize a +","");
10199                 /* if unsigned or not an integral type */
10200                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10201                         pic14_emitcode(";add a bit to something","");
10202                 } else {
10203                         
10204                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10205                         
10206                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10207                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10208                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10209                         } else
10210                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10211                         
10212                         offset = 0;
10213                         while(--big) {
10214                                 
10215                                 offset++;
10216                                 
10217                                 if(--small) {
10218                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10219                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10220                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10221                                         }
10222                                         
10223                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10224                                         emitSKPNC;
10225                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10226                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10227                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10228                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10229                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10230                                         
10231                                 } else {
10232                                         pic14_emitcode("rlf","known_zero,w");
10233                                         
10234                                         /*
10235                                         if right is signed
10236                                         btfsc  right,7
10237                                         addlw ff
10238                                         */
10239                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10240                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10241                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10242                                         } else {
10243                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10244                                         }
10245                                 }
10246                         }
10247                         ret = 1;
10248                 }
10249         }
10250         ret = 1;
10251         
10252 release:
10253         freeAsmop(right,NULL,ic,TRUE);
10254         freeAsmop(result,NULL,ic,TRUE);
10255         freeAsmop(nextright,NULL,ic,TRUE);
10256         freeAsmop(nextleft,NULL,ic,TRUE);
10257         if(ret)
10258                 nextic->generated = 1;
10259         
10260         return ret;
10261 #else
10262         return 0;
10263 #endif
10264 }
10265 /*-----------------------------------------------------------------*/
10266 /* genCast - gen code for casting                                  */
10267 /*-----------------------------------------------------------------*/
10268 static void genCast (iCode *ic)
10269 {
10270         operand *result = IC_RESULT(ic);
10271         sym_link *ctype = operandType(IC_LEFT(ic));
10272         sym_link *rtype = operandType(IC_RIGHT(ic));
10273         operand *right = IC_RIGHT(ic);
10274         int size, offset ;
10275         
10276         FENTRY;
10277         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10278         /* if they are equivalent then do nothing */
10279         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10280                 return ;
10281         
10282         aopOp(right,ic,FALSE) ;
10283         aopOp(result,ic,FALSE);
10284         
10285         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10286         
10287         /* if the result is a bit */
10288         if (AOP_TYPE(result) == AOP_CRY) {
10289         /* if the right size is a literal then
10290                 we know what the value is */
10291                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10292                 if (AOP_TYPE(right) == AOP_LIT) {
10293                         
10294                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10295                                 popGet(AOP(result),0));
10296                         
10297                         if (((int) operandLitValue(right))) 
10298                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
10299                                 AOP(result)->aopu.aop_dir,
10300                                 AOP(result)->aopu.aop_dir);
10301                         else
10302                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
10303                                 AOP(result)->aopu.aop_dir,
10304                                 AOP(result)->aopu.aop_dir);
10305                         
10306                         goto release;
10307                 }
10308                 
10309                 /* the right is also a bit variable */
10310                 if (AOP_TYPE(right) == AOP_CRY) {
10311                         
10312                         emitCLRC;
10313                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10314                         
10315                         pic14_emitcode("clrc","");
10316                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10317                                 AOP(right)->aopu.aop_dir,
10318                                 AOP(right)->aopu.aop_dir);
10319                         aopPut(AOP(result),"c",0);
10320                         goto release ;
10321                 }
10322                 
10323                 /* we need to or */
10324                 if (AOP_TYPE(right) == AOP_REG) {
10325                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10326                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
10327                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10328                 }
10329                 pic14_toBoolean(right);
10330                 aopPut(AOP(result),"a",0);
10331                 goto release ;
10332         }
10333         
10334         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10335                 int offset = 1;
10336                 size = AOP_SIZE(result);
10337                 
10338                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10339                 
10340                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10341                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10342                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10343                 
10344                 while (size--)
10345                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10346                 
10347                 goto release;
10348         }
10349         
10350         /* if they are the same size : or less */
10351         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10352                 
10353                 /* if they are in the same place */
10354                 if (pic14_sameRegs(AOP(right),AOP(result)))
10355                         goto release;
10356                 
10357                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10358                 if (IS_PTR_CONST(rtype))
10359                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10360                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10361                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10362                 
10363                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10364                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10365                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10366                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10367                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10368                         if(AOP_SIZE(result) <2)
10369                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10370                         
10371                 } else {
10372                         
10373                         /* if they in different places then copy */
10374                         size = AOP_SIZE(result);
10375                         offset = 0 ;
10376                         while (size--) {
10377                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10378                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10379                                 
10380                                 //aopPut(AOP(result),
10381                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10382                                 // offset);
10383                                 
10384                                 offset++;
10385                         }
10386                 }
10387                 goto release;
10388         }
10389         
10390         
10391         /* if the result is of type pointer */
10392         if (IS_PTR(ctype)) {
10393                 
10394                 int p_type;
10395                 sym_link *type = operandType(right);
10396                 sym_link *etype = getSpec(type);
10397                 DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10398                 
10399                 /* pointer to generic pointer */
10400                 if (IS_GENPTR(ctype)) {
10401                         char *l = zero;
10402                         
10403                         if (IS_PTR(type)) 
10404                                 p_type = DCL_TYPE(type);
10405                         else {
10406                                 /* we have to go by the storage class */
10407                                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10408                                 
10409                                 /*    if (SPEC_OCLS(etype)->codesp )  */
10410                                 /*        p_type = CPOINTER ;  */
10411                                 /*    else */
10412                                 /*        if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10413                                 /*      p_type = FPOINTER ; */
10414                                 /*        else */
10415                                 /*      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10416                                 /*          p_type = PPOINTER; */
10417                                 /*      else */
10418                                 /*          if (SPEC_OCLS(etype) == idata ) */
10419                                 /*        p_type = IPOINTER ; */
10420                                 /*          else */
10421                                 /*        p_type = POINTER ; */
10422                         }
10423                         
10424                         /* the first two bytes are known */
10425                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10426                         size = GPTRSIZE - 1; 
10427                         offset = 0 ;
10428                         while (size--) {
10429                                 if(offset < AOP_SIZE(right)) {
10430                                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10431                                         if ((AOP_TYPE(right) == AOP_PCODE) && 
10432                                                 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10433                                                 emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
10434                                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10435                                         } else { 
10436                                                 aopPut(AOP(result),
10437                                                         aopGet(AOP(right),offset,FALSE,FALSE),
10438                                                         offset);
10439                                         }
10440                                 } else 
10441                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
10442                                 offset++;
10443                         }
10444                         /* the last byte depending on type */
10445                         switch (p_type) {
10446                         case IPOINTER:
10447                         case POINTER:
10448                                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
10449                                 break;
10450                         case FPOINTER:
10451                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10452                                 l = one;
10453                                 break;
10454                         case CPOINTER:
10455                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10456                                 l = "#0x02";
10457                                 break;        
10458                         case PPOINTER:
10459                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10460                                 l = "#0x03";
10461                                 break;
10462                                 
10463                         default:
10464                                 /* this should never happen */
10465                                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10466                                         "got unknown pointer type");
10467                                 exit(1);
10468                         }
10469                         //aopPut(AOP(result),l, GPTRSIZE - 1);      
10470                         goto release ;
10471                 }
10472                 
10473                 /* just copy the pointers */
10474                 size = AOP_SIZE(result);
10475                 offset = 0 ;
10476                 while (size--) {
10477                         aopPut(AOP(result),
10478                                 aopGet(AOP(right),offset,FALSE,FALSE),
10479                                 offset);
10480                         offset++;
10481                 }
10482                 goto release ;
10483         }
10484         
10485         
10486         
10487         /* so we now know that the size of destination is greater
10488         than the size of the source.
10489         Now, if the next iCode is an operator then we might be
10490         able to optimize the operation without performing a cast.
10491         */
10492         if(genMixedOperation(ic))
10493                 goto release;
10494         
10495         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10496         
10497         /* we move to result for the size of source */
10498         size = AOP_SIZE(right);
10499         offset = 0 ;
10500         while (size--) {
10501                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10502                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10503                 offset++;
10504         }
10505         
10506         /* now depending on the sign of the destination */
10507         size = AOP_SIZE(result) - AOP_SIZE(right);
10508         /* if unsigned or not an integral type */
10509         if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10510                 while (size--)
10511                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10512         } else {
10513                 /* we need to extend the sign :{ */
10514                 
10515                 if(size == 1) {
10516                         /* Save one instruction of casting char to int */
10517                         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
10518                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10519                         emitpcode(POC_DECF,   popGet(AOP(result),offset));
10520                 } else {
10521                         emitpcodeNULLop(POC_CLRW);
10522                         
10523                         if(offset)
10524                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10525                         else
10526                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10527                         
10528                         emitpcode(POC_MOVLW,   popGetLit(0xff));
10529                         
10530                         while (size--)
10531                                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
10532                 }
10533         }
10534         
10535 release:
10536         freeAsmop(right,NULL,ic,TRUE);
10537         freeAsmop(result,NULL,ic,TRUE);
10538         
10539 }
10540
10541 /*-----------------------------------------------------------------*/
10542 /* genDjnz - generate decrement & jump if not zero instrucion      */
10543 /*-----------------------------------------------------------------*/
10544 static int genDjnz (iCode *ic, iCode *ifx)
10545 {
10546         symbol *lbl, *lbl1;
10547         FENTRY;
10548         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10549         
10550         if (!ifx)
10551                 return 0;
10552         
10553                 /* if the if condition has a false label
10554         then we cannot save */
10555         if (IC_FALSE(ifx))
10556                 return 0;
10557         
10558                 /* if the minus is not of the form 
10559         a = a - 1 */
10560         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10561                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10562                 return 0;
10563         
10564         if (operandLitValue(IC_RIGHT(ic)) != 1)
10565                 return 0;
10566         
10567                 /* if the size of this greater than one then no
10568         saving */
10569         if (getSize(operandType(IC_RESULT(ic))) > 1)
10570                 return 0;
10571         
10572         /* otherwise we can save BIG */
10573         lbl = newiTempLabel(NULL);
10574         lbl1= newiTempLabel(NULL);
10575         
10576         aopOp(IC_RESULT(ic),ic,FALSE);
10577         
10578         if (IS_AOP_PREG(IC_RESULT(ic))) {
10579                 pic14_emitcode("dec","%s",
10580                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10581                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10582                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10583         } else {  
10584                 
10585                 
10586                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10587                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10588                 
10589                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10590                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10591                 
10592         }
10593         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10594         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10595         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10596         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10597         
10598         
10599         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10600         ifx->generated = 1;
10601         return 1;
10602 }
10603
10604 /*-----------------------------------------------------------------*/
10605 /* genReceive - generate code for a receive iCode                  */
10606 /*-----------------------------------------------------------------*/
10607 static void genReceive (iCode *ic)
10608 {
10609         FENTRY;
10610         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10611         
10612         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10613                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10614                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10615                 
10616                 int size = getSize(operandType(IC_RESULT(ic)));
10617                 int offset =  fReturnSizePic - size;
10618                 while (size--) {
10619                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10620                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10621                         offset++;
10622                 }
10623                 aopOp(IC_RESULT(ic),ic,FALSE);
10624                 size = AOP_SIZE(IC_RESULT(ic));
10625                 offset = 0;
10626                 while (size--) {
10627                         pic14_emitcode ("pop","acc");
10628                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10629                 }
10630                 
10631         } else {
10632                 _G.accInUse++;
10633                 aopOp(IC_RESULT(ic),ic,FALSE);
10634                 _G.accInUse--;
10635                 assignResultValue(IC_RESULT(ic));
10636         }
10637         
10638         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10639 }
10640
10641 /*-----------------------------------------------------------------*/
10642 /* genDummyRead - generate code for dummy read of volatiles        */
10643 /*-----------------------------------------------------------------*/
10644 static void
10645 genDummyRead (iCode * ic)
10646 {
10647         FENTRY;
10648         pic14_emitcode ("; genDummyRead","");
10649         pic14_emitcode ("; not implemented","");
10650         
10651         ic = ic;
10652 }
10653
10654 /*-----------------------------------------------------------------*/
10655 /* genpic14Code - generate code for pic14 based controllers        */
10656 /*-----------------------------------------------------------------*/
10657 /*
10658 * At this point, ralloc.c has gone through the iCode and attempted
10659 * to optimize in a way suitable for a PIC. Now we've got to generate
10660 * PIC instructions that correspond to the iCode.
10661 *
10662 * Once the instructions are generated, we'll pass through both the
10663 * peep hole optimizer and the pCode optimizer.
10664 *-----------------------------------------------------------------*/
10665
10666 void genpic14Code (iCode *lic)
10667 {
10668         iCode *ic;
10669         int cln = 0;
10670         const char *cline;
10671         
10672         FENTRY;
10673         lineHead = lineCurr = NULL;
10674         
10675         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10676         addpBlock(pb);
10677         
10678         /* if debug information required */
10679         if (options.debug && currFunc) { 
10680                 if (currFunc) {
10681                         debugFile->writeFunction (currFunc, lic);
10682                 }
10683         }
10684         
10685         
10686         for (ic = lic ; ic ; ic = ic->next ) {
10687                 
10688                 //DEBUGpic14_emitcode(";ic","");
10689                 //fprintf (stderr, "in ic loop\n");
10690                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10691                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10692                 
10693                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10694                   cln = ic->lineno;
10695                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10696                   cline = printCLine (ic->filename, ic->lineno);
10697                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10698                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10699                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10700                 }
10701                 
10702                 if (options.iCodeInAsm) {
10703                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10704                 }
10705                 /* if the result is marked as
10706                 spilt and rematerializable or code for
10707                 this has already been generated then
10708                 do nothing */
10709                 if (resultRemat(ic) || ic->generated ) 
10710                         continue ;
10711                 
10712                 /* depending on the operation */
10713                 switch (ic->op) {
10714                 case '!' :
10715                         genNot(ic);
10716                         break;
10717                         
10718                 case '~' :
10719                         genCpl(ic);
10720                         break;
10721                         
10722                 case UNARYMINUS:
10723                         genUminus (ic);
10724                         break;
10725                         
10726                 case IPUSH:
10727                         genIpush (ic);
10728                         break;
10729                         
10730                 case IPOP:
10731                         /* IPOP happens only when trying to restore a 
10732                         spilt live range, if there is an ifx statement
10733                         following this pop then the if statement might
10734                         be using some of the registers being popped which
10735                         would destory the contents of the register so
10736                         we need to check for this condition and handle it */
10737                         if (ic->next            && 
10738                                 ic->next->op == IFX &&
10739                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10740                                 genIfx (ic->next,ic);
10741                         else
10742                                 genIpop (ic);
10743                         break; 
10744                         
10745                 case CALL:
10746                         genCall (ic);
10747                         break;
10748                         
10749                 case PCALL:
10750                         genPcall (ic);
10751                         break;
10752                         
10753                 case FUNCTION:
10754                         genFunction (ic);
10755                         break;
10756                         
10757                 case ENDFUNCTION:
10758                         genEndFunction (ic);
10759                         break;
10760                         
10761                 case RETURN:
10762                         genRet (ic);
10763                         break;
10764                         
10765                 case LABEL:
10766                         genLabel (ic);
10767                         break;
10768                         
10769                 case GOTO:
10770                         genGoto (ic);
10771                         break;
10772                         
10773                 case '+' :
10774                         genPlus (ic) ;
10775                         break;
10776                         
10777                 case '-' :
10778                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10779                                 genMinus (ic);
10780                         break;
10781                         
10782                 case '*' :
10783                         genMult (ic);
10784                         break;
10785                         
10786                 case '/' :
10787                         genDiv (ic) ;
10788                         break;
10789                         
10790                 case '%' :
10791                         genMod (ic);
10792                         break;
10793                         
10794                 case '>' :
10795                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10796                         break;
10797                         
10798                 case '<' :
10799                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10800                         break;
10801                         
10802                 case LE_OP:
10803                 case GE_OP:
10804                 case NE_OP:
10805                         
10806                         /* note these two are xlated by algebraic equivalence
10807                         during parsing SDCC.y */
10808                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10809                                 "got '>=' or '<=' shouldn't have come here");
10810                         break;  
10811                         
10812                 case EQ_OP:
10813                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10814                         break;      
10815                         
10816                 case AND_OP:
10817                         genAndOp (ic);
10818                         break;
10819                         
10820                 case OR_OP:
10821                         genOrOp (ic);
10822                         break;
10823                         
10824                 case '^' :
10825                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10826                         break;
10827                         
10828                 case '|' :
10829                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10830                         break;
10831                         
10832                 case BITWISEAND:
10833                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10834                         break;
10835                         
10836                 case INLINEASM:
10837                         genInline (ic);
10838                         break;
10839                         
10840                 case RRC:
10841                         genRRC (ic);
10842                         break;
10843                         
10844                 case RLC:
10845                         genRLC (ic);
10846                         break;
10847                         
10848                 case GETHBIT:
10849                         genGetHbit (ic);
10850                         break;
10851                         
10852                 case LEFT_OP:
10853                         genLeftShift (ic);
10854                         break;
10855                         
10856                 case RIGHT_OP:
10857                         genRightShift (ic);
10858                         break;
10859                         
10860                 case GET_VALUE_AT_ADDRESS:
10861                         genPointerGet(ic);
10862                         break;
10863                         
10864                 case '=' :
10865                         if (POINTER_SET(ic))
10866                                 genPointerSet(ic);
10867                         else
10868                                 genAssign(ic);
10869                         break;
10870                         
10871                 case IFX:
10872                         genIfx (ic,NULL);
10873                         break;
10874                         
10875                 case ADDRESS_OF:
10876                         genAddrOf (ic);
10877                         break;
10878                         
10879                 case JUMPTABLE:
10880                         genJumpTab (ic);
10881                         break;
10882                         
10883                 case CAST:
10884                         genCast (ic);
10885                         break;
10886                         
10887                 case RECEIVE:
10888                         genReceive(ic);
10889                         break;
10890                         
10891                 case SEND:
10892                         addSet(&_G.sendSet,ic);
10893                         break;
10894                         
10895                 case DUMMY_READ_VOLATILE:
10896                         genDummyRead (ic);
10897                         break;
10898                         
10899                 default :
10900                         ic = ic;
10901                 }
10902         }
10903
10904         
10905         /* now we are ready to call the
10906         peep hole optimizer */
10907         if (!options.nopeep) {
10908                 peepHole (&lineHead);
10909         }
10910         /* now do the actual printing */
10911         printLine (lineHead,codeOutFile);
10912         
10913 #ifdef PCODE_DEBUG
10914         DFPRINTF((stderr,"printing pBlock\n\n"));
10915         printpBlock(stdout,pb);
10916 #endif
10917         
10918         return;
10919 }
10920
10921 int
10922 aop_isLitLike (asmop *aop)
10923 {
10924   assert (aop);
10925   if (aop->type == AOP_LIT) return 1;
10926   if (aop->type == AOP_IMMD) return 1;
10927   if ((aop->type == AOP_PCODE) &&
10928                 ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
10929   {
10930     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10931      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10932     return 1;
10933   }
10934   return 0;
10935 }
10936
10937 int
10938 op_isLitLike (operand *op)
10939 {
10940   assert (op);
10941   if (aop_isLitLike (AOP(op))) return 1;
10942   return 0;
10943 }