f8b6b9d2e965be151fe583a6a6587631fb8f6b89
[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         unsigned 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 /* gen.h defines a macro emitpcode that should be used to call emitpcode
250  * as this allows for easy debugging (ever asked the question: where was
251  * this instruction geenrated? Here is the answer... */
252 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
253 {
254         if(pcop)
255                 addpCode2pBlock(pb,newpCode(poc,pcop));
256         else
257                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
258 }
259
260 void emitpcodeNULLop(PIC_OPCODE poc)
261 {
262         
263         addpCode2pBlock(pb,newpCode(poc,NULL));
264         
265 }
266
267
268 /*-----------------------------------------------------------------*/
269 /* pic14_emitcode - writes the code into a file : for now it is simple    */
270 /*-----------------------------------------------------------------*/
271 void pic14_emitcode (char *inst,char *fmt, ...)
272 {
273         va_list ap;
274         char lb[INITIAL_INLINEASM];  
275         unsigned char *lbp = lb;
276         
277         va_start(ap,fmt);   
278         
279         if (inst && *inst) {
280                 if (fmt && *fmt)
281                         sprintf(lb,"%s\t",inst);
282                 else
283                         sprintf(lb,"%s",inst);
284                 vsprintf(lb+(strlen(lb)),fmt,ap);
285         }  else
286                 vsprintf(lb,fmt,ap);
287         
288         while (isspace(*lbp)) lbp++;
289         
290         if (lbp && *lbp) 
291                 lineCurr = (lineCurr ?
292                 connectLine(lineCurr,newLineNode(lb)) :
293         (lineHead = newLineNode(lb)));
294         lineCurr->isInline = _G.inLine;
295         lineCurr->isDebug  = _G.debugLine;
296         
297         if(debug_verbose)
298                 addpCode2pBlock(pb,newpCodeCharP(lb));
299         
300         va_end(ap);
301 }
302
303 /*-----------------------------------------------------------------*/
304 /* pic14_emitDebuggerSymbol - associate the current code location  */
305 /*       with a debugger symbol                                                                            */
306 /*-----------------------------------------------------------------*/
307 void
308 pic14_emitDebuggerSymbol (char * debugSym)
309 {
310         _G.debugLine = 1;
311         pic14_emitcode ("", ";%s ==.", debugSym);
312         _G.debugLine = 0;
313 }
314
315
316 /*-----------------------------------------------------------------*/
317 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
318 /*-----------------------------------------------------------------*/
319 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
320 {
321         bool r0iu = FALSE , r1iu = FALSE;
322         bool r0ou = FALSE , r1ou = FALSE;
323         
324         /* the logic: if r0 & r1 used in the instruction
325         then we are in trouble otherwise */
326         
327         /* first check if r0 & r1 are used by this
328         instruction, in which case we are in trouble */
329         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
330                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
331         {
332                 goto endOfWorld;          
333         }
334         
335         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
336         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
337         
338         /* if no usage of r0 then return it */
339         if (!r0iu && !r0ou) {
340                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
341                 (*aopp)->type = AOP_R0;
342                 
343                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
344         }
345         
346         /* if no usage of r1 then return it */
347         if (!r1iu && !r1ou) {
348                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
349                 (*aopp)->type = AOP_R1;
350                 
351                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
352         }    
353         
354         /* now we know they both have usage */
355         /* if r0 not used in this instruction */
356         if (!r0iu) {
357                 /* push it if not already pushed */
358                 if (!_G.r0Pushed) {
359                         //pic14_emitcode ("push","%s",
360                         //                pic14_regWithIdx(R0_IDX)->dname);
361                         _G.r0Pushed++ ;
362                 }
363                 
364                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
365                 (*aopp)->type = AOP_R0;
366                 
367                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
368         }
369         
370         /* if r1 not used then */
371         
372         if (!r1iu) {
373                 /* push it if not already pushed */
374                 if (!_G.r1Pushed) {
375                         //pic14_emitcode ("push","%s",
376                         //                pic14_regWithIdx(R1_IDX)->dname);
377                         _G.r1Pushed++ ;
378                 }
379                 
380                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
381                 (*aopp)->type = AOP_R1;
382                 return pic14_regWithIdx(R1_IDX);
383         }
384         
385 endOfWorld :
386         /* I said end of world but not quite end of world yet */
387         /* if this is a result then we can push it on the stack*/
388         if (result) {
389                 (*aopp)->type = AOP_STK;        
390                 return NULL;
391         }
392         
393         /* other wise this is true end of the world */
394         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
395                 "getFreePtr should never reach here");
396         exit(0);
397 }
398
399 /*-----------------------------------------------------------------*/
400 /* newAsmop - creates a new asmOp                                                                  */
401 /*-----------------------------------------------------------------*/
402 asmop *newAsmop (short type)
403 {
404         asmop *aop;
405         
406         aop = Safe_calloc(1,sizeof(asmop));
407         aop->type = type;
408         return aop;
409 }
410
411 static void genSetDPTR(int n)
412 {
413         if (!n)
414         {
415                 pic14_emitcode(";", "Select standard DPTR");
416                 pic14_emitcode("mov", "dps, #0x00");
417         }
418         else
419         {
420                 pic14_emitcode(";", "Select alternate DPTR");
421                 pic14_emitcode("mov", "dps, #0x01");
422         }
423 }
424
425 /*-----------------------------------------------------------------*/
426 /* resolveIfx - converts an iCode ifx into a form more useful for  */
427 /*                              generating code                                                                    */
428 /*-----------------------------------------------------------------*/
429 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
430 {
431         if(!resIfx) 
432                 return;
433         
434         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
435         
436         resIfx->condition = 1;  /* assume that the ifx is true */
437         resIfx->generated = 0;  /* indicate that the ifx has not been used */
438         
439         if(!ifx) {
440                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
441                                                                                         /*
442                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
443                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
444                 */
445         } else {
446                 if(IC_TRUE(ifx)) {
447                         resIfx->lbl = IC_TRUE(ifx);
448                 } else {
449                         resIfx->lbl = IC_FALSE(ifx);
450                         resIfx->condition = 0;
451                 }
452                 /*
453                 if(IC_TRUE(ifx)) 
454                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
455                 if(IC_FALSE(ifx)) 
456                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
457                 */
458         }
459         
460         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
461         
462 }
463 /*-----------------------------------------------------------------*/
464 /* pointerCode - returns the code for a pointer type                       */
465 /*-----------------------------------------------------------------*/
466 static int pointerCode (sym_link *etype)
467 {
468         
469         return PTR_TYPE(SPEC_OCLS(etype));
470         
471 }
472
473 /*-----------------------------------------------------------------*/
474 /* aopForSym - for a true symbol                                                                   */
475 /*-----------------------------------------------------------------*/
476 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
477 {
478         asmop *aop;
479         memmap *space= SPEC_OCLS(sym->etype);
480         
481         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
482         /* if already has one */
483         if (sym->aop)
484                 return sym->aop;
485         
486         /* assign depending on the storage class */
487         /* if it is on the stack or indirectly addressable */
488         /* space we need to assign either r0 or r1 to it         */    
489         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
490                 sym->aop = aop = newAsmop(0);
491                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
492                 aop->size = getSize(sym->type);
493                 
494                 /* now assign the address of the variable to 
495                 the pointer register */
496                 if (aop->type != AOP_STK) {
497                         
498                         if (sym->onStack) {
499                                 if ( _G.accInUse )
500                                         pic14_emitcode("push","acc");
501                                 
502                                 pic14_emitcode("mov","a,_bp");
503                                 pic14_emitcode("add","a,#0x%02x",
504                                         ((sym->stack < 0) ?
505                                         ((char)(sym->stack - _G.nRegsSaved )) :
506                                 ((char)sym->stack)) & 0xff);
507                                 pic14_emitcode("mov","%s,a",
508                                         aop->aopu.aop_ptr->name);
509                                 
510                                 if ( _G.accInUse )
511                                         pic14_emitcode("pop","acc");
512                         } else
513                                 pic14_emitcode("mov","%s,#%s",
514                                 aop->aopu.aop_ptr->name,
515                                 sym->rname);
516                         aop->paged = space->paged;
517                 } else
518                         aop->aopu.aop_stk = sym->stack;
519                 return aop;
520         }
521         
522         if (sym->onStack && options.stack10bit)
523         {
524                 /* It's on the 10 bit stack, which is located in
525                 * far data space.
526                 */
527                 
528                 //DEBUGpic14_emitcode(";","%d",__LINE__);
529                 
530                 if ( _G.accInUse )
531                         pic14_emitcode("push","acc");
532                 
533                 pic14_emitcode("mov","a,_bp");
534                 pic14_emitcode("add","a,#0x%02x",
535                         ((sym->stack < 0) ?
536                         ((char)(sym->stack - _G.nRegsSaved )) :
537                 ((char)sym->stack)) & 0xff);
538                 
539                 genSetDPTR(1);
540                 pic14_emitcode ("mov","dpx1,#0x40");
541                 pic14_emitcode ("mov","dph1,#0x00");
542                 pic14_emitcode ("mov","dpl1, a");
543                 genSetDPTR(0);
544                 
545                 if ( _G.accInUse )
546                         pic14_emitcode("pop","acc");
547                 
548                 sym->aop = aop = newAsmop(AOP_DPTR2);
549                 aop->size = getSize(sym->type); 
550                 return aop;
551         }
552         
553         //DEBUGpic14_emitcode(";","%d",__LINE__);
554         /* if in bit space */
555         if (IN_BITSPACE(space)) {
556                 sym->aop = aop = newAsmop (AOP_CRY);
557                 aop->aopu.aop_dir = sym->rname ;
558                 aop->size = getSize(sym->type);
559                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
560                 return aop;
561         }
562         /* if it is in direct space */
563         if (IN_DIRSPACE(space)) {
564                 sym->aop = aop = newAsmop (AOP_DIR);
565                 aop->aopu.aop_dir = sym->rname ;
566                 aop->size = getSize(sym->type);
567                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
568                 return aop;
569         }
570         
571         /* special case for a function */
572         if (IS_FUNC(sym->type)) {   
573                 
574                 sym->aop = aop = newAsmop(AOP_PCODE);
575                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
576                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
577                 PCOI(aop->aopu.pcop)->_function = 1;
578                 PCOI(aop->aopu.pcop)->index = 0;
579                 aop->size = FPTRSIZE; 
580                 /*
581                 sym->aop = aop = newAsmop(AOP_IMMD);    
582                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
583                 strcpy(aop->aopu.aop_immd,sym->rname);
584                 aop->size = FPTRSIZE; 
585                 */
586                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
587                 return aop;
588         }
589         
590         
591         /* only remaining is far space */
592         /* in which case DPTR gets the address */
593         sym->aop = aop = newAsmop(AOP_PCODE);
594         
595         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
596         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
597         PCOI(aop->aopu.pcop)->index = 0;
598         
599         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
600                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
601         
602         allocDirReg (IC_LEFT(ic));
603         
604         aop->size = FPTRSIZE; 
605         /*
606         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
607         sym->aop = aop = newAsmop(AOP_DPTR);
608         pic14_emitcode ("mov","dptr,#%s", sym->rname);
609         aop->size = getSize(sym->type);
610         
611           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
612         */
613         
614         /* if it is in code space */
615         if (IN_CODESPACE(space))
616                 aop->code = 1;
617         
618         return aop;       
619 }
620
621 /*-----------------------------------------------------------------*/
622 /* aopForRemat - rematerialzes an object                                                   */
623 /*-----------------------------------------------------------------*/
624 static asmop *aopForRemat (operand *op) // x symbol *sym)
625 {
626         symbol *sym = OP_SYMBOL(op);
627         iCode *ic = NULL;
628         asmop *aop = newAsmop(AOP_PCODE);
629         int val = 0;
630         int offset = 0;
631         
632         ic = sym->rematiCode;
633         
634         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
635         if(IS_OP_POINTER(op)) {
636                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
637         }
638         for (;;) {
639                 if (ic->op == '+') {
640                         val += (int) operandLitValue(IC_RIGHT(ic));
641                 } else if (ic->op == '-') {
642                         val -= (int) operandLitValue(IC_RIGHT(ic));
643                 } else
644                         break;
645                 
646                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
647         }
648         
649         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
650         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
651         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
652         PCOI(aop->aopu.pcop)->index = val;
653         
654         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
655                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
656                 val, IS_PTR_CONST(operandType(op)));
657         
658         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
659         
660         allocDirReg (IC_LEFT(ic));
661         
662         return aop;              
663 }
664
665 int aopIdx (asmop *aop, int offset)
666 {
667         if(!aop)
668                 return -1;
669         
670         if(aop->type !=  AOP_REG)
671                 return -2;
672         
673         return aop->aopu.aop_reg[offset]->rIdx;
674         
675 }
676 /*-----------------------------------------------------------------*/
677 /* regsInCommon - two operands have some registers in common       */
678 /*-----------------------------------------------------------------*/
679 static bool regsInCommon (operand *op1, operand *op2)
680 {
681         symbol *sym1, *sym2;
682         int i;
683         
684         /* if they have registers in common */
685         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
686                 return FALSE ;
687         
688         sym1 = OP_SYMBOL(op1);
689         sym2 = OP_SYMBOL(op2);
690         
691         if (sym1->nRegs == 0 || sym2->nRegs == 0)
692                 return FALSE ;
693         
694         for (i = 0 ; i < sym1->nRegs ; i++) {
695                 int j;
696                 if (!sym1->regs[i])
697                         continue ;
698                 
699                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
700                         if (!sym2->regs[j])
701                                 continue ;
702                         
703                         if (sym2->regs[j] == sym1->regs[i])
704                                 return TRUE ;
705                 }
706         }
707         
708         return FALSE ;
709 }
710
711 /*-----------------------------------------------------------------*/
712 /* operandsEqu - equivalent                                                                        */
713 /*-----------------------------------------------------------------*/
714 static bool operandsEqu ( operand *op1, operand *op2)
715 {
716         symbol *sym1, *sym2;
717         
718         /* if they not symbols */
719         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
720                 return FALSE;
721         
722         sym1 = OP_SYMBOL(op1);
723         sym2 = OP_SYMBOL(op2);
724         
725         /* if both are itemps & one is spilt
726         and the other is not then false */
727         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
728                 sym1->isspilt != sym2->isspilt )
729                 return FALSE ;
730         
731         /* if they are the same */
732         if (sym1 == sym2)
733                 return TRUE ;
734         
735         if (sym1->rname[0] && sym2->rname[0]
736                 && strcmp (sym1->rname, sym2->rname) == 0)
737                 return TRUE;
738         
739         
740         /* if left is a tmp & right is not */
741         if (IS_ITEMP(op1)  && 
742                 !IS_ITEMP(op2) &&
743                 sym1->isspilt  &&
744                 (sym1->usl.spillLoc == sym2))
745                 return TRUE;
746         
747         if (IS_ITEMP(op2)  && 
748                 !IS_ITEMP(op1) &&
749                 sym2->isspilt  &&
750                 sym1->level > 0 &&
751                 (sym2->usl.spillLoc == sym1))
752                 return TRUE ;
753         
754         return FALSE ;
755 }
756
757 /*-----------------------------------------------------------------*/
758 /* pic14_sameRegs - two asmops have the same registers             */
759 /*-----------------------------------------------------------------*/
760 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
761 {
762         int i;
763         
764         if (aop1 == aop2)
765                 return TRUE ;
766         
767         if (aop1->type != AOP_REG ||
768                 aop2->type != AOP_REG )
769                 return FALSE ;
770         
771         if (aop1->size != aop2->size )
772                 return FALSE ;
773         
774         for (i = 0 ; i < aop1->size ; i++ )
775                 if (aop1->aopu.aop_reg[i] !=
776                         aop2->aopu.aop_reg[i] )
777                         return FALSE ;
778                 
779                 return TRUE ;
780 }
781
782 /*-----------------------------------------------------------------*/
783 /* aopOp - allocates an asmop for an operand  :                    */
784 /*-----------------------------------------------------------------*/
785 void aopOp (operand *op, iCode *ic, bool result)
786 {
787         asmop *aop;
788         symbol *sym;
789         int i;
790         
791         if (!op)
792                 return ;
793         
794         /* if this a literal */
795         if (IS_OP_LITERAL(op)) {
796                 op->aop = aop = newAsmop(AOP_LIT);
797                 aop->aopu.aop_lit = op->operand.valOperand;
798                 aop->size = getSize(operandType(op));
799                 return;
800         }
801         
802         {
803                 sym_link *type = operandType(op);
804                 if(IS_PTR_CONST(type))
805                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
806         }
807         
808         /* if already has a asmop then continue */
809         if (op->aop)
810                 return ;
811         
812         /* if the underlying symbol has a aop */
813         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
814                 DEBUGpic14_emitcode(";","%d",__LINE__);
815                 op->aop = OP_SYMBOL(op)->aop;
816                 return;
817         }
818         
819         /* if this is a true symbol */
820         if (IS_TRUE_SYMOP(op)) {          
821                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
822                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
823                 return ;
824         }
825         
826         /* this is a temporary : this has
827         only four choices :
828         a) register
829         b) spillocation
830         c) rematerialize 
831         d) conditional   
832         e) can be a return use only */
833         
834         sym = OP_SYMBOL(op);
835         
836         
837         /* if the type is a conditional */
838         if (sym->regType == REG_CND) {
839                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
840                 aop->size = 0;
841                 return;
842         }
843         
844         /* if it is spilt then two situations
845         a) is rematerialize 
846         b) has a spill location */
847         if (sym->isspilt || sym->nRegs == 0) {
848                 
849                 DEBUGpic14_emitcode(";","%d",__LINE__);
850                 /* rematerialize it NOW */
851                 if (sym->remat) {
852                         
853                         sym->aop = op->aop = aop = aopForRemat (op);
854                         aop->size = getSize(sym->type);
855                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
856                         return;
857                 }
858                 
859 #if 0
860                 /* WREG is not usable as an ordinary operand with PIC architecture,
861                  * one might introduce a scratch register that can be used to make
862                  * WREG accesible as an operand... disable WREG for now */
863                 if (sym->accuse) {
864                         int i;
865                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
866                         aop->size = getSize(sym->type);
867                         for ( i = 0 ; i < 2 ; i++ )
868                                 aop->aopu.aop_str[i] = accUse[i];
869                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
870                         return;  
871                 }
872 #endif
873                 
874                 if (sym->ruonly ) {
875                         if(sym->isptr) {        // && sym->uptr 
876                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
877                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
878                                 
879                                 //PCOI(aop->aopu.pcop)->_const = 0;
880                                 //PCOI(aop->aopu.pcop)->index = 0;
881                                 /*
882                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
883                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
884                                 */
885                                 //allocDirReg (IC_LEFT(ic));
886                                 
887                                 aop->size = getSize(sym->type);
888                                 DEBUGpic14_emitcode(";","%d",__LINE__);
889                                 return;
890                                 
891                         } else {
892                                 
893                                 unsigned i;
894                                 
895                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
896                                 aop->size = getSize(sym->type);
897                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
898                                         aop->aopu.aop_str[i] = fReturn[i];
899                                 
900                                 DEBUGpic14_emitcode(";","%d",__LINE__);
901                                 return;
902                         }
903                 }
904                 
905                 /* else spill location  */
906                 if (sym->usl.spillLoc)
907                 {
908                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
909                         {
910                                 /* force a new aop if sizes differ */
911                                 sym->usl.spillLoc->aop = NULL;
912                         }
913                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
914                                 __FUNCTION__,__LINE__,
915                                 sym->usl.spillLoc->rname,
916                                 sym->rname, sym->usl.spillLoc->offset);
917                 
918                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
919                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
920                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
921                                 getSize(sym->type), 
922                                 sym->usl.spillLoc->offset);
923                         aop->size = getSize(sym->type);
924                 
925                         return;
926                 }
927         }
928         
929         {
930                 sym_link *type = operandType(op);
931                 if(IS_PTR_CONST(type)) 
932                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
933         }
934         
935         /* must be in a register */
936         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
937         sym->aop = op->aop = aop = newAsmop(AOP_REG);
938         aop->size = sym->nRegs;
939         for ( i = 0 ; i < sym->nRegs ;i++)
940                 aop->aopu.aop_reg[i] = sym->regs[i];
941 }
942
943 /*-----------------------------------------------------------------*/
944 /* freeAsmop - free up the asmop given to an operand                       */
945 /*----------------------------------------------------------------*/
946 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
947 {       
948         asmop *aop ;
949         
950         if (!op)
951                 aop = aaop;
952         else 
953                 aop = op->aop;
954         
955         if (!aop)
956                 return ;
957         
958         if (aop->freed)
959                 goto dealloc; 
960         
961         aop->freed = 1;
962         
963         /* depending on the asmop type only three cases need work AOP_RO
964         , AOP_R1 && AOP_STK */
965 #if 0
966         switch (aop->type) {
967         case AOP_R0 :
968                 if (_G.r0Pushed ) {
969                         if (pop) {
970                                 pic14_emitcode ("pop","ar0");     
971                                 _G.r0Pushed--;
972                         }
973                 }
974                 bitVectUnSetBit(ic->rUsed,R0_IDX);
975                 break;
976                 
977         case AOP_R1 :
978                 if (_G.r1Pushed ) {
979                         if (pop) {
980                                 pic14_emitcode ("pop","ar1");
981                                 _G.r1Pushed--;
982                         }
983                 }
984                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
985                 break;
986                 
987         case AOP_STK :
988                 {
989                         int sz = aop->size;      
990                         int stk = aop->aopu.aop_stk + aop->size;
991                         bitVectUnSetBit(ic->rUsed,R0_IDX);
992                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
993                         
994                         getFreePtr(ic,&aop,FALSE);
995                         
996                         if (options.stack10bit)
997                         {
998                                 /* I'm not sure what to do here yet... */
999                                 /* #STUB */
1000                                 fprintf(stderr, 
1001                                         "*** Warning: probably generating bad code for "
1002                                         "10 bit stack mode.\n");
1003                         }
1004                         
1005                         if (stk) {
1006                                 pic14_emitcode ("mov","a,_bp");
1007                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1008                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1009                         } else {
1010                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1011                         }
1012                         
1013                         while (sz--) {
1014                                 pic14_emitcode("pop","acc");
1015                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1016                                 if (!sz) break;
1017                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1018                         }
1019                         op->aop = aop;
1020                         freeAsmop(op,NULL,ic,TRUE);
1021                         if (_G.r0Pushed) {
1022                                 pic14_emitcode("pop","ar0");
1023                                 _G.r0Pushed--;
1024                         }
1025                         
1026                         if (_G.r1Pushed) {
1027                                 pic14_emitcode("pop","ar1");
1028                                 _G.r1Pushed--;
1029                         }         
1030                 }
1031         }
1032 #endif
1033         
1034 dealloc:
1035         /* all other cases just dealloc */
1036         if (op ) {
1037                 op->aop = NULL;
1038                 if (IS_SYMOP(op)) {
1039                         OP_SYMBOL(op)->aop = NULL;      
1040                         /* if the symbol has a spill */
1041                         if (SPIL_LOC(op))
1042                                 SPIL_LOC(op)->aop = NULL;
1043                 }
1044         }
1045 }
1046
1047 /*-----------------------------------------------------------------*/
1048 /* aopGet - for fetching value of the aop                                                  */
1049 /*-----------------------------------------------------------------*/
1050 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1051 {
1052         char *s = buffer ;
1053         char *rs;
1054         
1055         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1056         /* offset is greater than
1057         size then zero */
1058         if (offset > (aop->size - 1) &&
1059                 aop->type != AOP_LIT)
1060                 return zero;
1061         
1062         /* depending on type */
1063         switch (aop->type) {
1064                 
1065         case AOP_R0:
1066         case AOP_R1:
1067                 DEBUGpic14_emitcode(";","%d",__LINE__);
1068                 /* if we need to increment it */           
1069                 while (offset > aop->coff) {            
1070                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1071                         aop->coff++;
1072                 }
1073                 
1074                 while (offset < aop->coff) {
1075                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1076                         aop->coff--;
1077                 }
1078                 
1079                 aop->coff = offset ;
1080                 if (aop->paged) {
1081                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1082                         return (dname ? "acc" : "a");
1083                 }               
1084                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1085                 rs = Safe_calloc(1,strlen(s)+1);
1086                 strcpy(rs,s);   
1087                 return rs;
1088                 
1089         case AOP_DPTR:
1090         case AOP_DPTR2:
1091                 DEBUGpic14_emitcode(";","%d",__LINE__);
1092                 if (aop->type == AOP_DPTR2)
1093                 {
1094                         genSetDPTR(1);
1095                 }
1096                 
1097                 while (offset > aop->coff) {
1098                         pic14_emitcode ("inc","dptr");
1099                         aop->coff++;
1100                 }
1101                 
1102                 while (offset < aop->coff) {            
1103                         pic14_emitcode("lcall","__decdptr");
1104                         aop->coff--;
1105                 }
1106                 
1107                 aop->coff = offset;
1108                 if (aop->code) {
1109                         pic14_emitcode("clr","a");
1110                         pic14_emitcode("movc","a,@a+dptr");
1111                 }
1112                 else {
1113                         pic14_emitcode("movx","a,@dptr");
1114                 }
1115                 
1116                 if (aop->type == AOP_DPTR2)
1117                 {
1118                         genSetDPTR(0);
1119                 }
1120                 
1121                 return (dname ? "acc" : "a");
1122                 
1123                 
1124         case AOP_IMMD:
1125                 if (bit16) 
1126                         sprintf (s,"%s",aop->aopu.aop_immd);
1127                 else
1128                         if (offset) 
1129                                 sprintf(s,"(%s >> %d)",
1130                                 aop->aopu.aop_immd,
1131                                 offset*8);
1132                         else
1133                                 sprintf(s,"%s",
1134                                 aop->aopu.aop_immd);
1135                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1136                         rs = Safe_calloc(1,strlen(s)+1);
1137                         strcpy(rs,s);   
1138                         return rs;
1139                         
1140         case AOP_DIR:
1141                 if (offset) {
1142                         sprintf(s,"(%s + %d)",
1143                                 aop->aopu.aop_dir,
1144                                 offset);
1145                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1146                 } else
1147                         sprintf(s,"%s",aop->aopu.aop_dir);
1148                 rs = Safe_calloc(1,strlen(s)+1);
1149                 strcpy(rs,s);   
1150                 return rs;
1151                 
1152         case AOP_REG:
1153                 //if (dname) 
1154                 //        return aop->aopu.aop_reg[offset]->dname;
1155                 //else
1156                 return aop->aopu.aop_reg[offset]->name;
1157                 
1158         case AOP_CRY:
1159                 //pic14_emitcode(";","%d",__LINE__);
1160                 return aop->aopu.aop_dir;
1161                 
1162         case AOP_ACC:
1163                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1164                 return "AOP_accumulator_bug";
1165                 
1166         case AOP_LIT:
1167                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1168                 rs = Safe_calloc(1,strlen(s)+1);
1169                 strcpy(rs,s);   
1170                 return rs;
1171                 
1172         case AOP_STR:
1173                 aop->coff = offset ;
1174                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1175                         dname)
1176                         return "acc";
1177                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1178                 
1179                 return aop->aopu.aop_str[offset];
1180                 
1181         case AOP_PCODE:
1182                 {
1183                         pCodeOp *pcop = aop->aopu.pcop;
1184                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1185                         if(pcop->name) {
1186                                 if (offset) {
1187                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1188                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1189                                 } else {
1190                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1191                                         sprintf(s,"%s", pcop->name);
1192                                 }
1193                         } else
1194                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1195                         
1196                 }
1197                 rs = Safe_calloc(1,strlen(s)+1);
1198                 strcpy(rs,s);   
1199                 return rs;
1200                 
1201   }
1202   
1203   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1204           "aopget got unsupported aop->type");
1205   exit(0);
1206 }
1207
1208
1209 /*-----------------------------------------------------------------*/
1210 /* popGetTempReg - create a new temporary pCodeOp                                  */
1211 /*-----------------------------------------------------------------*/
1212 pCodeOp *popGetTempReg(void)
1213 {
1214         
1215         pCodeOp *pcop;
1216         
1217         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1218         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1219                 PCOR(pcop)->r->wasUsed=1;
1220                 PCOR(pcop)->r->isFree=0;
1221         }
1222         
1223         return pcop;
1224 }
1225
1226 /*-----------------------------------------------------------------*/
1227 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1228 /*-----------------------------------------------------------------*/
1229 void popReleaseTempReg(pCodeOp *pcop)
1230 {
1231         
1232         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1233                 PCOR(pcop)->r->isFree = 1;
1234         
1235 }
1236 /*-----------------------------------------------------------------*/
1237 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1238 /*-----------------------------------------------------------------*/
1239 pCodeOp *popGetLabel(unsigned int key)
1240 {
1241         
1242         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1243         
1244         if(key>(unsigned int)max_key)
1245                 max_key = key;
1246         
1247         return newpCodeOpLabel(NULL,key+100+labelOffset);
1248 }
1249
1250 /*-------------------------------------------------------------------*/
1251 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1252 /*-------------------------------------------------------------------*/
1253 pCodeOp *popGetHighLabel(unsigned int key)
1254 {
1255         pCodeOp *pcop;
1256         pcop = popGetLabel(key);
1257         PCOLAB(pcop)->offset = 1;
1258         return pcop;
1259 }
1260
1261 /*-----------------------------------------------------------------*/
1262 /* popGetLit - asm operator to pcode operator conversion                           */
1263 /*-----------------------------------------------------------------*/
1264 pCodeOp *popGetLit(unsigned int lit)
1265 {
1266         
1267         return newpCodeOpLit(lit);
1268 }
1269
1270 /*-----------------------------------------------------------------*/
1271 /* popGetImmd - asm operator to pcode immediate conversion                 */
1272 /*-----------------------------------------------------------------*/
1273 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1274 {
1275         
1276         return newpCodeOpImmd(name, offset,index, 0, is_func);
1277 }
1278
1279
1280 /*-----------------------------------------------------------------*/
1281 /* popGetWithString - asm operator to pcode operator conversion                    */
1282 /*-----------------------------------------------------------------*/
1283 pCodeOp *popGetWithString(char *str, int isExtern)
1284 {
1285         pCodeOp *pcop;
1286         
1287         
1288         if(!str) {
1289                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1290                 exit (1);
1291         }
1292         
1293         pcop = newpCodeOp(str,PO_STR);
1294         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1295         
1296         return pcop;
1297 }
1298
1299 /*-----------------------------------------------------------------*/
1300 /* popRegFromString -                                                                                      */
1301 /*-----------------------------------------------------------------*/
1302 pCodeOp *popRegFromString(char *str, int size, int offset)
1303 {
1304         
1305         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1306         pcop->type = PO_DIR;
1307         
1308         DEBUGpic14_emitcode(";","%d",__LINE__);
1309         
1310         if(!str)
1311                 str = "BAD_STRING";
1312         
1313         pcop->name = Safe_calloc(1,strlen(str)+1);
1314         strcpy(pcop->name,str);
1315         
1316         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1317         
1318         PCOR(pcop)->r = dirregWithName(pcop->name);
1319         if(PCOR(pcop)->r == NULL) {
1320                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1321                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1322                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1323         } else {
1324                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1325         }
1326         PCOR(pcop)->instance = offset;
1327         
1328         return pcop;
1329 }
1330
1331 /*-----------------------------------------------------------------*/
1332 /*-----------------------------------------------------------------*/
1333 pCodeOp *popRegFromIdx(int rIdx)
1334 {
1335         pCodeOp *pcop;
1336         
1337         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1338                 __FUNCTION__,__LINE__,rIdx);
1339         
1340         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1341         
1342         PCOR(pcop)->rIdx = rIdx;
1343         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1344         PCOR(pcop)->r->isFree = 0;
1345         PCOR(pcop)->r->wasUsed = 1;
1346         
1347         pcop->type = PCOR(pcop)->r->pc_type;
1348         
1349         
1350         return pcop;
1351 }
1352
1353 /*-----------------------------------------------------------------*/
1354 /* popGet - asm operator to pcode operator conversion                      */
1355 /*-----------------------------------------------------------------*/
1356 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1357 {
1358         //char *s = buffer ;
1359         //char *rs;
1360         
1361         pCodeOp *pcop;
1362         
1363         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1364         /* offset is greater than
1365         size then zero */
1366
1367         if (!(offset >= 0 && ((offset < aop->size) || (aop->size == 0))))
1368         {
1369           fprintf (stderr, "%s:%u: offset=%d, aop-type:%s, size:%d\n", __FILE__, __LINE__, offset, AopType (aop->type), aop->size);
1370         }
1371         assert (offset >= 0 && ((offset < aop->size) || (aop->size == 0)));
1372         
1373         /* XXX: still needed for BIT operands (AOP_CRY) */
1374         if (offset > (aop->size - 1) &&
1375                 aop->type != AOP_LIT)
1376                 return NULL;  //zero;
1377         
1378         /* depending on type */
1379         switch (aop->type) {
1380                 
1381         case AOP_R0:
1382         case AOP_R1:
1383         case AOP_DPTR:
1384         case AOP_DPTR2:
1385         case AOP_ACC:
1386                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1387                 return NULL;
1388                 
1389         case AOP_IMMD:
1390                 DEBUGpic14_emitcode(";","%d",__LINE__);
1391                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1392                 
1393         case AOP_DIR:
1394                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1395 #if 0
1396                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1397                 pcop->type = PO_DIR;
1398                 
1399                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1400                 strcpy(pcop->name,aop->aopu.aop_dir);   
1401                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1402                 if(PCOR(pcop)->r == NULL) {
1403                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1404                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1405                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1406                 } else {
1407                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1408                 }
1409                 PCOR(pcop)->instance = offset;
1410                 
1411                 return pcop;
1412 #endif
1413                 
1414         case AOP_REG:
1415                 {
1416                         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1417                         
1418                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1419                         PCOR(pcop)->rIdx = rIdx;
1420                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1421                         PCOR(pcop)->r->wasUsed=1;
1422                         PCOR(pcop)->r->isFree=0;
1423                         
1424                         PCOR(pcop)->instance = offset;
1425                         pcop->type = PCOR(pcop)->r->pc_type;
1426                         //rs = aop->aopu.aop_reg[offset]->name;
1427                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1428                         return pcop;
1429                 }
1430                 
1431         case AOP_CRY:
1432                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1433                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1434                 //if(PCOR(pcop)->r == NULL)
1435                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1436                 return pcop;
1437                 
1438         case AOP_LIT:
1439                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1440                 
1441         case AOP_STR:
1442                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1443                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1444                 /*
1445                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1446                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1447                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1448                 pcop->type = PCOR(pcop)->r->pc_type;
1449                 pcop->name = PCOR(pcop)->r->name;
1450                 
1451                   return pcop;
1452                 */
1453                 
1454         case AOP_PCODE:
1455                 pcop = NULL;
1456                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1457                         __LINE__, 
1458                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1459                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1460                 switch (aop->aopu.pcop->type)
1461                 {
1462                 case PO_IMMEDIATE:
1463                   pcop = pCodeOpCopy (aop->aopu.pcop);
1464                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1465                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1466                   PCOI(pcop)->index += offset;
1467                   //PCOI(pcop)->offset = 0;
1468                   break;
1469                 case PO_DIR:
1470                   pcop = pCodeOpCopy (aop->aopu.pcop);
1471                   PCOR(pcop)->instance = offset;
1472                   break;
1473                 default:
1474                   assert ( !"unhandled pCode type" );
1475                   break;
1476                 } // switch
1477                 return pcop;
1478         }
1479         
1480         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1481                 "popGet got unsupported aop->type");
1482         exit(0);
1483 }
1484
1485 /*-----------------------------------------------------------------*/
1486 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1487 /*              (for non-PO_IMMEDIATEs this is the same as poGet)  */
1488 /*-----------------------------------------------------------------*/
1489 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1490 {
1491   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1492   {
1493     pCodeOp *pcop = aop->aopu.pcop;
1494     pcop = pCodeOpCopy (pcop);
1495     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1496      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1497     PCOI(pcop)->offset += offset;
1498     PCOI(pcop)->index += index;
1499     return pcop;
1500   } else {
1501     return popGet (aop, offset + index);
1502   }
1503 }
1504
1505 /*-----------------------------------------------------------------*/
1506 /* aopPut - puts a string for a aop                                                        */
1507 /*-----------------------------------------------------------------*/
1508 void aopPut (asmop *aop, char *s, int offset)
1509 {
1510         char *d = buffer ;
1511         symbol *lbl ;
1512         
1513         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1514         
1515         if (aop->size && offset > ( aop->size - 1)) {
1516                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1517                         "aopPut got offset > aop->size");
1518                 exit(0);
1519         }
1520         
1521         /* will assign value to value */
1522         /* depending on where it is ofcourse */
1523         switch (aop->type) {
1524         case AOP_DIR:
1525                 if (offset) {
1526                         sprintf(d,"(%s + %d)",
1527                                 aop->aopu.aop_dir,offset);
1528                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1529                         
1530                 } else
1531                         sprintf(d,"%s",aop->aopu.aop_dir);
1532                 
1533                 if (strcmp(d,s)) {
1534                         DEBUGpic14_emitcode(";","%d",__LINE__);
1535                         if(strcmp(s,"W"))
1536                                 pic14_emitcode("movf","%s,w",s);
1537                         pic14_emitcode("movwf","%s",d);
1538                         
1539                         if(strcmp(s,"W")) {
1540                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1541                                 if(offset >= aop->size) {
1542                                         emitpcode(POC_CLRF,popGet(aop,offset));
1543                                         break;
1544                                 } else
1545                                         emitpcode(POC_MOVLW,popGetImmd(s,offset,0,0));
1546                         }
1547                         
1548                         emitpcode(POC_MOVWF,popGet(aop,offset));
1549                         
1550                         
1551                 }
1552                 break;
1553                 
1554         case AOP_REG:
1555                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1556                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1557                         /*
1558                         if (*s == '@'             ||
1559                         strcmp(s,"r0") == 0 ||
1560                         strcmp(s,"r1") == 0 ||
1561                         strcmp(s,"r2") == 0 ||
1562                         strcmp(s,"r3") == 0 ||
1563                         strcmp(s,"r4") == 0 ||
1564                         strcmp(s,"r5") == 0 ||
1565                         strcmp(s,"r6") == 0 || 
1566                         strcmp(s,"r7") == 0 )
1567                         pic14_emitcode("mov","%s,%s  ; %d",
1568                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1569                         else
1570                         */
1571                         
1572                         if(strcmp(s,"W")==0 )
1573                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1574                         
1575                         pic14_emitcode("movwf","%s",
1576                                 aop->aopu.aop_reg[offset]->name);
1577                         
1578                         if(strcmp(s,zero)==0) {
1579                                 emitpcode(POC_CLRF,popGet(aop,offset));
1580                                 
1581                         } else if(strcmp(s,"W")==0) {
1582                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1583                                 pcop->type = PO_GPR_REGISTER;
1584                                 
1585                                 PCOR(pcop)->rIdx = -1;
1586                                 PCOR(pcop)->r = NULL;
1587                                 
1588                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1589                                 pcop->name = Safe_strdup(s);
1590                                 emitpcode(POC_MOVFW,pcop);
1591                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1592                         } else if(strcmp(s,one)==0) {
1593                                 emitpcode(POC_CLRF,popGet(aop,offset));
1594                                 emitpcode(POC_INCF,popGet(aop,offset));
1595                         } else {
1596                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1597                         }
1598                 }
1599                 break;
1600                 
1601         case AOP_DPTR:
1602         case AOP_DPTR2:
1603                 
1604                 if (aop->type == AOP_DPTR2)
1605                 {
1606                         genSetDPTR(1);
1607                 }
1608                 
1609                 if (aop->code) {
1610                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1611                                 "aopPut writting to code space");
1612                         exit(0);
1613                 }
1614                 
1615                 while (offset > aop->coff) {
1616                         aop->coff++;
1617                         pic14_emitcode ("inc","dptr");
1618                 }
1619                 
1620                 while (offset < aop->coff) {
1621                         aop->coff-- ;
1622                         pic14_emitcode("lcall","__decdptr");
1623                 }
1624                 
1625                 aop->coff = offset;
1626                 
1627                 /* if not in accumulater */
1628                 MOVA(s);
1629                 
1630                 pic14_emitcode ("movx","@dptr,a");
1631                 
1632                 if (aop->type == AOP_DPTR2)
1633                 {
1634                         genSetDPTR(0);
1635                 }
1636                 break;
1637                 
1638         case AOP_R0:
1639         case AOP_R1:
1640                 while (offset > aop->coff) {
1641                         aop->coff++;
1642                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1643                 }
1644                 while (offset < aop->coff) {
1645                         aop->coff-- ;
1646                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1647                 }
1648                 aop->coff = offset;
1649                 
1650                 if (aop->paged) {
1651                         MOVA(s);                         
1652                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1653                         
1654                 } else
1655                         if (*s == '@') {
1656                                 MOVA(s);
1657                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1658                         } else
1659                                 if (strcmp(s,"r0") == 0 ||
1660                                         strcmp(s,"r1") == 0 ||
1661                                         strcmp(s,"r2") == 0 ||
1662                                         strcmp(s,"r3") == 0 ||
1663                                         strcmp(s,"r4") == 0 ||
1664                                         strcmp(s,"r5") == 0 ||
1665                                         strcmp(s,"r6") == 0 || 
1666                                         strcmp(s,"r7") == 0 ) {
1667                                         char buffer[10];
1668                                         sprintf(buffer,"a%s",s);
1669                                         pic14_emitcode("mov","@%s,%s",
1670                                                 aop->aopu.aop_ptr->name,buffer);
1671                                 } else
1672                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1673                                 
1674                                 break;
1675                                 
1676         case AOP_STK:
1677                 if (strcmp(s,"a") == 0)
1678                         pic14_emitcode("push","acc");
1679                 else
1680                         pic14_emitcode("push","%s",s);
1681                 
1682                 break;
1683                 
1684         case AOP_CRY:
1685                 /* if bit variable */
1686                 if (!aop->aopu.aop_dir) {
1687                         pic14_emitcode("clr","a");
1688                         pic14_emitcode("rlc","a");
1689                 } else {
1690                         if (s == zero) 
1691                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1692                         else
1693                                 if (s == one)
1694                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1695                                 else
1696                                         if (!strcmp(s,"c"))
1697                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1698                                         else {
1699                                                 lbl = newiTempLabel(NULL);
1700                                                 
1701                                                 if (strcmp(s,"a")) {
1702                                                         MOVA(s);
1703                                                 }
1704                                                 pic14_emitcode("clr","c");
1705                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1706                                                 pic14_emitcode("cpl","c");
1707                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1708                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1709                                         }
1710                 }
1711                 break;
1712                 
1713         case AOP_STR:
1714                 aop->coff = offset;
1715                 if (strcmp(aop->aopu.aop_str[offset],s))
1716                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1717                 break;
1718                 
1719         case AOP_ACC:
1720                 aop->coff = offset;
1721                 if (!offset && (strcmp(s,"acc") == 0))
1722                         break;
1723                 
1724                 if (strcmp(aop->aopu.aop_str[offset],s))
1725                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1726                 break;
1727                 
1728         default :
1729                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1730                         "aopPut got unsupported aop->type");
1731                 exit(0);
1732         }
1733         
1734 }
1735
1736 /*-----------------------------------------------------------------*/
1737 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1738 /*-----------------------------------------------------------------*/
1739 void mov2w (asmop *aop, int offset)
1740 {
1741         
1742         if(!aop)
1743                 return;
1744         
1745         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1746         
1747         if ( aop_isLitLike (aop) )
1748                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1749         else
1750                 emitpcode(POC_MOVFW,popGet(aop,offset));
1751         
1752 }
1753
1754 /*-----------------------------------------------------------------*/
1755 /* reAdjustPreg - points a register back to where it should        */
1756 /*-----------------------------------------------------------------*/
1757 static void reAdjustPreg (asmop *aop)
1758 {
1759         int size ;
1760         
1761         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1762         aop->coff = 0;
1763         if ((size = aop->size) <= 1)
1764                 return ;
1765         size-- ;
1766         switch (aop->type) {
1767         case AOP_R0 :
1768         case AOP_R1 :
1769                 while (size--)
1770                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1771                 break;                  
1772         case AOP_DPTR :
1773         case AOP_DPTR2:
1774                 if (aop->type == AOP_DPTR2)
1775                 {
1776                         genSetDPTR(1);
1777                 } 
1778                 while (size--)
1779                 {
1780                         pic14_emitcode("lcall","__decdptr");
1781                 }
1782                 
1783                 if (aop->type == AOP_DPTR2)
1784                 {
1785                         genSetDPTR(0);
1786                 }
1787                 break;
1788                 
1789         }
1790         
1791 }
1792
1793
1794 #if 0
1795 /*-----------------------------------------------------------------*/
1796 /* opIsGptr: returns non-zero if the passed operand is             */
1797 /* a generic pointer type.                                         */
1798 /*-----------------------------------------------------------------*/ 
1799 static int opIsGptr(operand *op)
1800 {
1801         sym_link *type = operandType(op);
1802         
1803         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1804         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1805         {
1806                 return 1;
1807         }
1808         return 0;          
1809 }
1810 #endif
1811
1812 /*-----------------------------------------------------------------*/
1813 /* pic14_getDataSize - get the operand data size                   */
1814 /*-----------------------------------------------------------------*/
1815 int pic14_getDataSize(operand *op)
1816 {
1817         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1818         
1819         
1820         return AOP_SIZE(op);
1821         
1822         // tsd- in the pic port, the genptr size is 1, so this code here
1823         // fails. ( in the 8051 port, the size was 4).
1824 #if 0
1825         int size;
1826         size = AOP_SIZE(op);
1827         if (size == GPTRSIZE)
1828         {
1829                 sym_link *type = operandType(op);
1830                 if (IS_GENPTR(type))
1831                 {
1832                         /* generic pointer; arithmetic operations
1833                         * should ignore the high byte (pointer type).
1834                         */
1835                         size--;
1836                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1837                 }
1838         }
1839         return size;
1840 #endif
1841 }
1842
1843 /*-----------------------------------------------------------------*/
1844 /* pic14_outAcc - output Acc                                       */
1845 /*-----------------------------------------------------------------*/
1846 void pic14_outAcc(operand *result)
1847 {
1848         int size,offset;
1849         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1850         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
1851         
1852         
1853         size = pic14_getDataSize(result);
1854         if(size){
1855                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
1856                 size--;
1857                 offset = 1;
1858                 /* unsigned or positive */
1859                 while(size--)
1860                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1861         }
1862         
1863 }
1864
1865 /*-----------------------------------------------------------------*/
1866 /* pic14_outBitC - output a bit C                                  */
1867 /*-----------------------------------------------------------------*/
1868 void pic14_outBitC(operand *result)
1869 {
1870         
1871         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1872         /* if the result is bit */
1873         if (AOP_TYPE(result) == AOP_CRY) 
1874                 aopPut(AOP(result),"c",0);
1875         else {
1876                 pic14_emitcode("clr","a  ; %d", __LINE__);
1877                 pic14_emitcode("rlc","a");
1878                 pic14_outAcc(result);
1879         }
1880 }
1881
1882 /*-----------------------------------------------------------------*/
1883 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
1884 /*-----------------------------------------------------------------*/
1885 void pic14_toBoolean(operand *oper)
1886 {
1887         int size = AOP_SIZE(oper) - 1;
1888         int offset = 1;
1889         
1890         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1891         
1892         if ( AOP_TYPE(oper) != AOP_ACC) {
1893                 emitpcode(POC_MOVFW,popGet(AOP(oper),0));
1894         }
1895         while (size--) {
1896                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
1897         }
1898 }
1899
1900
1901 /*-----------------------------------------------------------------*/
1902 /* genNot - generate code for ! operation                          */
1903 /*-----------------------------------------------------------------*/
1904 static void genNot (iCode *ic)
1905 {
1906         //symbol *tlbl;
1907         int size;
1908
1909         FENTRY;
1910         
1911         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1912         /* assign asmOps to operand & result */
1913         aopOp (IC_LEFT(ic),ic,FALSE);
1914         aopOp (IC_RESULT(ic),ic,TRUE);
1915         
1916         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1917         /* if in bit space then a special case */
1918         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1919                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1920                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
1921                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
1922                 } else {
1923                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1924                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
1925                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1926                 }
1927                 goto release;
1928         }
1929         
1930         assert (!pic14_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))));
1931         size = AOP_SIZE(IC_LEFT(ic));
1932         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
1933         mov2w (AOP(IC_LEFT(ic)),0);
1934         while (--size > 0)
1935         {
1936           if (aop_isLitLike (AOP(IC_LEFT(ic))))
1937             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
1938           else
1939             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
1940         }
1941         emitSKPNZ;
1942         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
1943         goto release;
1944         
1945 release:        
1946         /* release the aops */
1947         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1948         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1949 }
1950
1951
1952 /*-----------------------------------------------------------------*/
1953 /* genCpl - generate code for complement                                                   */
1954 /*-----------------------------------------------------------------*/
1955 static void genCpl (iCode *ic)
1956 {
1957         operand *left, *result;
1958         int size, offset=0;  
1959         
1960         FENTRY;
1961         
1962         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1963         aopOp((left = IC_LEFT(ic)),ic,FALSE);
1964         aopOp((result=IC_RESULT(ic)),ic,TRUE);
1965         
1966         /* if both are in bit space then 
1967         a special case */
1968         if (AOP_TYPE(result) == AOP_CRY &&
1969                 AOP_TYPE(left) == AOP_CRY ) { 
1970                 
1971                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
1972                 pic14_emitcode("cpl","c"); 
1973                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
1974                 goto release; 
1975         } 
1976         
1977         size = AOP_SIZE(result);
1978         while (size--) {
1979                 
1980                 if(AOP_TYPE(left) == AOP_ACC) 
1981                         emitpcode(POC_XORLW, popGetLit(0xff));
1982                 else
1983                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
1984                 
1985                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
1986                 offset++;
1987         }
1988         
1989         
1990 release:
1991         /* release the aops */
1992         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1993         freeAsmop(result,NULL,ic,TRUE);
1994 }
1995
1996 /*-----------------------------------------------------------------*/
1997 /* genUminusFloat - unary minus for floating points                        */
1998 /*-----------------------------------------------------------------*/
1999 static void genUminusFloat(operand *op,operand *result)
2000 {
2001         int size ,offset =0 ;
2002         char *l;
2003         
2004         FENTRY;
2005
2006         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2007         /* for this we just need to flip the 
2008         first it then copy the rest in place */
2009         size = AOP_SIZE(op) - 1;
2010         l = aopGet(AOP(op),3,FALSE,FALSE);
2011         
2012         MOVA(l);          
2013         
2014         pic14_emitcode("cpl","acc.7");
2015         aopPut(AOP(result),"a",3);      
2016         
2017         while(size--) {
2018                 aopPut(AOP(result),
2019                         aopGet(AOP(op),offset,FALSE,FALSE),
2020                         offset);
2021                 offset++;
2022         }                
2023 }
2024
2025 /*-----------------------------------------------------------------*/
2026 /* genUminus - unary minus code generation                                                 */
2027 /*-----------------------------------------------------------------*/
2028 static void genUminus (iCode *ic)
2029 {
2030         int size, i;
2031         sym_link *optype, *rtype;
2032         
2033         FENTRY;
2034         
2035         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2036         /* assign asmops */
2037         aopOp(IC_LEFT(ic),ic,FALSE);
2038         aopOp(IC_RESULT(ic),ic,TRUE);
2039         
2040         /* if both in bit space then special
2041         case */
2042         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2043                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2044                 
2045                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2046                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2047                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2048                 
2049                 goto release; 
2050         } 
2051         
2052         optype = operandType(IC_LEFT(ic));
2053         rtype = operandType(IC_RESULT(ic));
2054         
2055         /* if float then do float stuff */
2056         if (IS_FLOAT(optype)) {
2057                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2058                 goto release;
2059         }
2060         
2061         /* otherwise subtract from zero by taking the 2's complement */
2062         size = AOP_SIZE(IC_LEFT(ic));
2063         
2064         for(i=0; i<size; i++) {
2065                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2066                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2067                 else {
2068                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2069                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2070                 }
2071         }
2072         
2073         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2074         for(i=1; i<size; i++) {
2075                 emitSKPNZ;
2076                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2077         }
2078         
2079 release:
2080         /* release the aops */
2081         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2082         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2083 }
2084
2085 /*-----------------------------------------------------------------*/
2086 /* saveRegisters - will look for a call and save the registers     */
2087 /*-----------------------------------------------------------------*/
2088 static void saveRegisters(iCode *lic) 
2089 {
2090         int i;
2091         iCode *ic;
2092         bitVect *rsave;
2093         sym_link *dtype;
2094         
2095         FENTRY;
2096
2097         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2098         /* look for call */
2099         for (ic = lic ; ic ; ic = ic->next) 
2100                 if (ic->op == CALL || ic->op == PCALL)
2101                         break;
2102                 
2103                 if (!ic) {
2104                         fprintf(stderr,"found parameter push with no function call\n");
2105                         return ;
2106                 }
2107                 
2108                 /* if the registers have been saved already then
2109                 do nothing */
2110                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2111                         return ;
2112                 
2113                         /* find the registers in use at this time 
2114                 and push them away to safety */
2115                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2116                         ic->rUsed);
2117                 
2118                 ic->regsSaved = 1;
2119                 if (options.useXstack) {
2120                         if (bitVectBitValue(rsave,R0_IDX))
2121                                 pic14_emitcode("mov","b,r0");
2122                         pic14_emitcode("mov","r0,%s",spname);
2123                         for (i = 0 ; i < pic14_nRegs ; i++) {
2124                                 if (bitVectBitValue(rsave,i)) {
2125                                         if (i == R0_IDX)
2126                                                 pic14_emitcode("mov","a,b");
2127                                         else
2128                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2129                                         pic14_emitcode("movx","@r0,a");
2130                                         pic14_emitcode("inc","r0");
2131                                 }
2132                         }
2133                         pic14_emitcode("mov","%s,r0",spname);
2134                         if (bitVectBitValue(rsave,R0_IDX))
2135                                 pic14_emitcode("mov","r0,b");     
2136                 }// else
2137                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2138                 //        if (bitVectBitValue(rsave,i))
2139                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2140                 //}
2141                 
2142                 dtype = operandType(IC_LEFT(ic));
2143                 if (currFunc && dtype && 
2144                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2145                         IFFUNC_ISISR(currFunc->type) &&
2146                         !ic->bankSaved) 
2147                         
2148                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2149                 
2150 }
2151 /*-----------------------------------------------------------------*/
2152 /* unsaveRegisters - pop the pushed registers                                      */
2153 /*-----------------------------------------------------------------*/
2154 static void unsaveRegisters (iCode *ic)
2155 {
2156         int i;
2157         bitVect *rsave;
2158         
2159         FENTRY;
2160
2161         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2162         /* find the registers in use at this time 
2163         and push them away to safety */
2164         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2165                 ic->rUsed);
2166         
2167         if (options.useXstack) {
2168                 pic14_emitcode("mov","r0,%s",spname); 
2169                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2170                         if (bitVectBitValue(rsave,i)) {
2171                                 pic14_emitcode("dec","r0");
2172                                 pic14_emitcode("movx","a,@r0");
2173                                 if (i == R0_IDX)
2174                                         pic14_emitcode("mov","b,a");
2175                                 else
2176                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2177                         }       
2178                         
2179                 }
2180                 pic14_emitcode("mov","%s,r0",spname);
2181                 if (bitVectBitValue(rsave,R0_IDX))
2182                         pic14_emitcode("mov","r0,b");
2183         } //else
2184         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2185         //      if (bitVectBitValue(rsave,i))
2186         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2187         //}
2188         
2189 }  
2190
2191
2192 /*-----------------------------------------------------------------*/
2193 /* pushSide -                            */
2194 /*-----------------------------------------------------------------*/
2195 static void pushSide(operand * oper, int size)
2196 {
2197 #if 0
2198         int offset = 0;
2199         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2200         while (size--) {
2201                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2202                 if (AOP_TYPE(oper) != AOP_REG &&
2203                         AOP_TYPE(oper) != AOP_DIR &&
2204                         strcmp(l,"a") ) {
2205                         pic14_emitcode("mov","a,%s",l);
2206                         pic14_emitcode("push","acc");
2207                 } else
2208                         pic14_emitcode("push","%s",l);
2209         }
2210 #endif
2211 }
2212
2213 /*-----------------------------------------------------------------*/
2214 /* assignResultValue -                           */
2215 /*-----------------------------------------------------------------*/
2216 static void assignResultValue(operand * oper)
2217 {
2218         int size = AOP_SIZE(oper);
2219         
2220         FENTRY;
2221
2222         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2223         
2224         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2225         
2226         while (size--) {
2227                 if (GpsuedoStkPtr++)
2228                         emitpcode(POC_MOVFW,popRegFromIdx(Gstack_base_addr+2-GpsuedoStkPtr));
2229                 emitpcode(POC_MOVWF, popGet(AOP(oper),size));
2230         }
2231 }
2232
2233
2234 /*-----------------------------------------------------------------*/
2235 /* genIpush - genrate code for pushing this gets a little complex  */
2236 /*-----------------------------------------------------------------*/
2237 static void genIpush (iCode *ic)
2238 {
2239         FENTRY;
2240         
2241         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2242 #if 0
2243         int size, offset = 0 ;
2244         char *l;
2245         
2246         
2247         /* if this is not a parm push : ie. it is spill push 
2248         and spill push is always done on the local stack */
2249         if (!ic->parmPush) {
2250                 
2251                 /* and the item is spilt then do nothing */
2252                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2253                         return ;
2254                 
2255                 aopOp(IC_LEFT(ic),ic,FALSE);
2256                 size = AOP_SIZE(IC_LEFT(ic));
2257                 /* push it on the stack */
2258                 while(size--) {
2259                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2260                         if (*l == '#') {
2261                                 MOVA(l);
2262                                 l = "acc";
2263                         }
2264                         pic14_emitcode("push","%s",l);
2265                 }
2266                 return ;                
2267         }
2268         
2269         /* this is a paramter push: in this case we call
2270         the routine to find the call and save those
2271         registers that need to be saved */   
2272         saveRegisters(ic);
2273         
2274         /* then do the push */
2275         aopOp(IC_LEFT(ic),ic,FALSE);
2276         
2277         
2278         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2279         size = AOP_SIZE(IC_LEFT(ic));
2280         
2281         while (size--) {
2282                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2283                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2284                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2285                         strcmp(l,"a") ) {
2286                         pic14_emitcode("mov","a,%s",l);
2287                         pic14_emitcode("push","acc");
2288                 } else
2289                         pic14_emitcode("push","%s",l);
2290         }         
2291         
2292         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2293 #endif
2294 }
2295
2296 /*-----------------------------------------------------------------*/
2297 /* genIpop - recover the registers: can happen only for spilling   */
2298 /*-----------------------------------------------------------------*/
2299 static void genIpop (iCode *ic)
2300 {
2301         FENTRY;
2302
2303         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2304 #if 0
2305         int size,offset ;
2306         
2307         
2308         /* if the temp was not pushed then */
2309         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2310                 return ;
2311         
2312         aopOp(IC_LEFT(ic),ic,FALSE);
2313         size = AOP_SIZE(IC_LEFT(ic));
2314         offset = (size-1);
2315         while (size--) 
2316                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2317                 FALSE,TRUE));
2318         
2319         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2320 #endif
2321 }
2322
2323 /*-----------------------------------------------------------------*/
2324 /* unsaverbank - restores the resgister bank from stack                    */
2325 /*-----------------------------------------------------------------*/
2326 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2327 {
2328         FENTRY;
2329
2330         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2331 #if 0
2332         int i;
2333         asmop *aop ;
2334         regs *r = NULL;
2335         
2336         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2337         if (popPsw) {
2338                 if (options.useXstack) {
2339                         aop = newAsmop(0);
2340                         r = getFreePtr(ic,&aop,FALSE);
2341                         
2342                         
2343                         pic14_emitcode("mov","%s,_spx",r->name);
2344                         pic14_emitcode("movx","a,@%s",r->name);
2345                         pic14_emitcode("mov","psw,a");
2346                         pic14_emitcode("dec","%s",r->name);
2347                         
2348                 }else
2349                         pic14_emitcode ("pop","psw");
2350         }
2351         
2352         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2353                 if (options.useXstack) {           
2354                         pic14_emitcode("movx","a,@%s",r->name);
2355                         //pic14_emitcode("mov","(%s+%d),a",
2356                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2357                         pic14_emitcode("dec","%s",r->name);
2358                         
2359                 } else 
2360                         pic14_emitcode("pop",""); //"(%s+%d)",
2361                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2362         }
2363         
2364         if (options.useXstack) {
2365                 
2366                 pic14_emitcode("mov","_spx,%s",r->name);
2367                 freeAsmop(NULL,aop,ic,TRUE);
2368                 
2369         }
2370 #endif 
2371 }
2372
2373 /*-----------------------------------------------------------------*/
2374 /* saverbank - saves an entire register bank on the stack                  */
2375 /*-----------------------------------------------------------------*/
2376 static void saverbank (int bank, iCode *ic, bool pushPsw)
2377 {
2378         FENTRY;
2379
2380         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2381 #if 0
2382         int i;
2383         asmop *aop ;
2384         regs *r = NULL;
2385         
2386         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2387         if (options.useXstack) {
2388                 
2389                 aop = newAsmop(0);
2390                 r = getFreePtr(ic,&aop,FALSE);  
2391                 pic14_emitcode("mov","%s,_spx",r->name);
2392                 
2393         }
2394         
2395         for (i = 0 ; i < pic14_nRegs ;i++) {
2396                 if (options.useXstack) {
2397                         pic14_emitcode("inc","%s",r->name);
2398                         //pic14_emitcode("mov","a,(%s+%d)",
2399                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2400                         pic14_emitcode("movx","@%s,a",r->name);                 
2401                 } else 
2402                         pic14_emitcode("push","");// "(%s+%d)",
2403                 //regspic14[i].base,8*bank+regspic14[i].offset);
2404         }
2405         
2406         if (pushPsw) {
2407                 if (options.useXstack) {
2408                         pic14_emitcode("mov","a,psw");
2409                         pic14_emitcode("movx","@%s,a",r->name); 
2410                         pic14_emitcode("inc","%s",r->name);
2411                         pic14_emitcode("mov","_spx,%s",r->name);                 
2412                         freeAsmop (NULL,aop,ic,TRUE);
2413                         
2414                 } else
2415                         pic14_emitcode("push","psw");
2416                 
2417                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2418         }
2419         ic->bankSaved = 1;
2420 #endif
2421 }
2422
2423 /*-----------------------------------------------------------------*/
2424 /* genCall - generates a call statement                                                    */
2425 /*-----------------------------------------------------------------*/
2426 static void genCall (iCode *ic)
2427 {
2428         sym_link *dtype;         
2429         symbol *sym;
2430         unsigned char *name;
2431         int isExtern;
2432         
2433         FENTRY;
2434
2435         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2436         
2437         /* if caller saves & we have not saved then */
2438         if (!ic->regsSaved)
2439                 saveRegisters(ic);
2440         
2441                 /* if we are calling a function that is not using
2442                 the same register bank then we need to save the
2443         destination registers on the stack */
2444         dtype = operandType(IC_LEFT(ic));
2445         if (currFunc && dtype && 
2446                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2447                 IFFUNC_ISISR(currFunc->type) &&
2448                 !ic->bankSaved) 
2449                 
2450                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2451         
2452         /* if send set is not empty the assign */
2453         if (_G.sendSet) {
2454                 iCode *sic;
2455                 /* For the Pic port, there is no data stack.
2456                 * So parameters passed to functions are stored
2457                 * in registers. (The pCode optimizer will get
2458                 * rid of most of these :).
2459                 */
2460                 int psuedoStkPtr=-1;
2461                 int firstTimeThruLoop = 1;
2462                 
2463                 _G.sendSet = reverseSet(_G.sendSet);
2464                 
2465                 /* First figure how many parameters are getting passed */
2466                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2467                 sic = setNextItem(_G.sendSet)) {
2468                         
2469                         aopOp(IC_LEFT(sic),sic,FALSE);
2470                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2471                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2472                 }
2473                 
2474                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2475                 sic = setNextItem(_G.sendSet)) {
2476                         int size, offset = 0;
2477                         
2478                         aopOp(IC_LEFT(sic),sic,FALSE);
2479                         size = AOP_SIZE(IC_LEFT(sic));
2480                         
2481                         while (size--) {
2482                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2483                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2484                                 
2485                                 if(!firstTimeThruLoop) {
2486                                         /* If this is not the first time we've been through the loop
2487                                         * then we need to save the parameter in a temporary
2488                                         * register. The last byte of the last parameter is
2489                                         * passed in W. */
2490                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2491                                         
2492                                 }
2493                                 firstTimeThruLoop=0;
2494                                 
2495                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2496                                 offset++;
2497                         }
2498                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2499                 }
2500                 _G.sendSet = NULL;
2501         }
2502         /* make the call */
2503         sym = OP_SYMBOL(IC_LEFT(ic));
2504         name = sym->rname[0] ? sym->rname : sym->name;
2505         isExtern = IS_EXTERN(sym->etype);
2506         if (isExtern) {
2507                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2508         }
2509         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2510         if (isExtern) {
2511                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2512         }
2513         GpsuedoStkPtr=0;
2514         /* if we need assign a result value */
2515         if ((IS_ITEMP(IC_RESULT(ic)) && 
2516                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2517                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2518                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2519                 
2520                 _G.accInUse++;
2521                 aopOp(IC_RESULT(ic),ic,FALSE);
2522                 _G.accInUse--;
2523                 
2524                 assignResultValue(IC_RESULT(ic));
2525                 
2526                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2527                         AopType(AOP_TYPE(IC_RESULT(ic))));
2528                 
2529                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2530         }
2531         
2532         /* adjust the stack for parameters if 
2533         required */
2534         if (ic->parmBytes) {
2535                 int i;
2536                 if (ic->parmBytes > 3) {
2537                         pic14_emitcode("mov","a,%s",spname);
2538                         pic14_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2539                         pic14_emitcode("mov","%s,a",spname);
2540                 } else 
2541                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2542                                 pic14_emitcode("dec","%s",spname);
2543                         
2544         }
2545         
2546         /* if register bank was saved then pop them */
2547         if (ic->bankSaved)
2548                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2549         
2550         /* if we hade saved some registers then unsave them */
2551         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2552                 unsaveRegisters (ic);
2553         
2554         
2555 }
2556
2557 /*-----------------------------------------------------------------*/
2558 /* genPcall - generates a call by pointer statement                        */
2559 /*-----------------------------------------------------------------*/
2560 static void genPcall (iCode *ic)
2561 {
2562         sym_link *dtype;
2563         symbol *albl = newiTempLabel(NULL);
2564         symbol *blbl = newiTempLabel(NULL);
2565         PIC_OPCODE poc;
2566         pCodeOp *pcop;
2567         operand *left;
2568         
2569         FENTRY;
2570
2571         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2572         /* if caller saves & we have not saved then */
2573         if (!ic->regsSaved)
2574                 saveRegisters(ic);
2575         
2576                 /* if we are calling a function that is not using
2577                 the same register bank then we need to save the
2578         destination registers on the stack */
2579         dtype = operandType(IC_LEFT(ic));
2580         if (currFunc && dtype && 
2581                 IFFUNC_ISISR(currFunc->type) &&
2582                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2583                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2584         
2585         left = IC_LEFT(ic);
2586         aopOp(left,ic,FALSE);
2587         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2588         
2589         pushSide(IC_LEFT(ic), FPTRSIZE);
2590         
2591         /* if send set is not empty, assign parameters */
2592         if (_G.sendSet) {
2593                 
2594                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2595                 /* no way to pass args - W always gets used to make the call */
2596         }
2597         /* first idea - factor out a common helper function and call it.
2598         But don't know how to get it generated only once in its own block
2599         
2600         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2601                 char *rname;
2602                 char *buffer;
2603                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2604                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2605                 buffer = Safe_calloc(1,strlen(rname)+16);
2606                 sprintf(buffer, "%s_goto_helper", rname);
2607                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2608                 free(buffer);
2609         }
2610         */
2611         emitpcode(POC_CALL,popGetLabel(albl->key));
2612         pcop = popGetLabel(blbl->key);
2613         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
2614         emitpcode(POC_GOTO,pcop);
2615         emitpLabel(albl->key);
2616         
2617         poc = ( aop_isLitLike (AOP(left)) ? POC_MOVLW : POC_MOVFW );
2618         
2619         emitpcode(poc,popGetAddr(AOP(left),1,0));
2620         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2621         emitpcode(poc,popGetAddr(AOP(left),0,0));
2622         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2623         
2624         emitpLabel(blbl->key);
2625         
2626         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2627         
2628         /* if we need to assign a result value */
2629         if ((IS_ITEMP(IC_RESULT(ic)) &&
2630                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2631                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2632                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2633                 
2634                 _G.accInUse++;
2635                 aopOp(IC_RESULT(ic),ic,FALSE);
2636                 _G.accInUse--;
2637                 
2638                 assignResultValue(IC_RESULT(ic));
2639                 
2640                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2641         }
2642         
2643         /* if register bank was saved then unsave them */
2644         if (currFunc && dtype && 
2645                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2646                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2647         
2648                 /* if we hade saved some registers then
2649         unsave them */
2650         if (ic->regsSaved)
2651                 unsaveRegisters (ic);
2652         
2653 }
2654
2655 /*-----------------------------------------------------------------*/
2656 /* resultRemat - result  is rematerializable                                       */
2657 /*-----------------------------------------------------------------*/
2658 static int resultRemat (iCode *ic)
2659 {
2660         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2661         FENTRY;
2662
2663         if (SKIP_IC(ic) || ic->op == IFX)
2664                 return 0;
2665         
2666         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2667                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2668                 if (sym->remat && !POINTER_SET(ic)) 
2669                         return 1;
2670         }
2671         
2672         return 0;
2673 }
2674
2675 #if defined(__BORLANDC__) || defined(_MSC_VER)
2676 #define STRCASECMP stricmp
2677 #else
2678 #define STRCASECMP strcasecmp
2679 #endif
2680
2681 #if 0
2682 /*-----------------------------------------------------------------*/
2683 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2684 /*-----------------------------------------------------------------*/
2685 static bool inExcludeList(char *s)
2686 {
2687         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2688         int i =0;
2689         
2690         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2691         if (options.excludeRegs[i] &&
2692                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2693                 return FALSE ;
2694         
2695         for ( i = 0 ; options.excludeRegs[i]; i++) {
2696                 if (options.excludeRegs[i] &&
2697                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2698                         return TRUE;
2699         }
2700         return FALSE ;
2701 }
2702 #endif
2703
2704 /*-----------------------------------------------------------------*/
2705 /* genFunction - generated code for function entry                                 */
2706 /*-----------------------------------------------------------------*/
2707 static void genFunction (iCode *ic)
2708 {
2709         symbol *sym;
2710         sym_link *ftype;
2711         
2712         FENTRY;
2713
2714         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2715         
2716         labelOffset += (max_key+4);
2717         max_key=0;
2718         GpsuedoStkPtr=0;
2719         _G.nRegsSaved = 0;
2720         /* create the function header */
2721         pic14_emitcode(";","-----------------------------------------");
2722         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2723         pic14_emitcode(";","-----------------------------------------");
2724         
2725         pic14_emitcode("","%s:",sym->rname);
2726         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2727         
2728         ftype = operandType(IC_LEFT(ic));
2729         
2730         /* if critical function then turn interrupts off */
2731         if (IFFUNC_ISCRITICAL(ftype))
2732                 pic14_emitcode("clr","ea");
2733         
2734                 /* here we need to generate the equates for the
2735         register bank if required */
2736 #if 0
2737         if (FUNC_REGBANK(ftype) != rbank) {
2738                 int i ;
2739                 
2740                 rbank = FUNC_REGBANK(ftype);
2741                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2742                         if (strcmp(regspic14[i].base,"0") == 0)
2743                                 pic14_emitcode("","%s = 0x%02x",
2744                                 regspic14[i].dname,
2745                                 8*rbank+regspic14[i].offset);
2746                         else
2747                                 pic14_emitcode ("","%s = %s + 0x%02x",
2748                                 regspic14[i].dname,
2749                                 regspic14[i].base,
2750                                 8*rbank+regspic14[i].offset);
2751                 }
2752         }
2753 #endif
2754         
2755         /* if this is an interrupt service routine */
2756         if (IFFUNC_ISISR(sym->type)) {
2757         /*  already done in pic14createInterruptVect() - delete me
2758         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2759         emitpcodeNULLop(POC_NOP);
2760         emitpcodeNULLop(POC_NOP);
2761         emitpcodeNULLop(POC_NOP);
2762                 */
2763                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2764                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2765                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2766                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2767                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2768                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2769                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2770                 
2771                 pBlockConvert2ISR(pb);
2772 #if 0  
2773                 if (!inExcludeList("acc"))              
2774                         pic14_emitcode ("push","acc");  
2775                 if (!inExcludeList("b"))
2776                         pic14_emitcode ("push","b");
2777                 if (!inExcludeList("dpl"))
2778                         pic14_emitcode ("push","dpl");
2779                 if (!inExcludeList("dph"))
2780                         pic14_emitcode ("push","dph");
2781                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2782                 {
2783                         pic14_emitcode ("push", "dpx");
2784                         /* Make sure we're using standard DPTR */
2785                         pic14_emitcode ("push", "dps");
2786                         pic14_emitcode ("mov", "dps, #0x00");
2787                         if (options.stack10bit)
2788                         { 
2789                                 /* This ISR could conceivably use DPTR2. Better save it. */
2790                                 pic14_emitcode ("push", "dpl1");
2791                                 pic14_emitcode ("push", "dph1");
2792                                 pic14_emitcode ("push", "dpx1");
2793                         }
2794                 }
2795                 /* if this isr has no bank i.e. is going to
2796                 run with bank 0 , then we need to save more
2797                 registers :-) */
2798                 if (!FUNC_REGBANK(sym->type)) {
2799                         
2800                 /* if this function does not call any other
2801                 function then we can be economical and
2802                         save only those registers that are used */
2803                         if (! IFFUNC_HASFCALL(sym->type)) {
2804                                 int i;
2805                                 
2806                                 /* if any registers used */
2807                                 if (sym->regsUsed) {
2808                                         /* save the registers used */
2809                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2810                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2811                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2812                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2813                                         }
2814                                 }
2815                                 
2816                         } else {
2817                         /* this function has    a function call cannot
2818                         determines register usage so we will have the
2819                                 entire bank */
2820                                 saverbank(0,ic,FALSE);
2821                         }       
2822                 }
2823 #endif
2824         } else {
2825         /* if callee-save to be used for this function
2826                 then save the registers being used in this function */
2827                 if (IFFUNC_CALLEESAVES(sym->type)) {
2828                         int i;
2829                         
2830                         /* if any registers used */
2831                         if (sym->regsUsed) {
2832                                 /* save the registers used */
2833                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2834                                         if (bitVectBitValue(sym->regsUsed,i) ||
2835                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
2836                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2837                                                 _G.nRegsSaved++;
2838                                         }
2839                                 }
2840                         }
2841                 }
2842         }
2843         
2844         /* set the register bank to the desired value */
2845         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
2846                 pic14_emitcode("push","psw");
2847                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
2848         }
2849         
2850         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2851                 
2852                 if (options.useXstack) {
2853                         pic14_emitcode("mov","r0,%s",spname);
2854                         pic14_emitcode("mov","a,_bp");
2855                         pic14_emitcode("movx","@r0,a");
2856                         pic14_emitcode("inc","%s",spname);
2857                 }
2858                 else
2859                 {
2860                         /* set up the stack */
2861                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
2862                 }
2863                 pic14_emitcode ("mov","_bp,%s",spname);
2864         }
2865         
2866         /* adjust the stack for the function */
2867         if (sym->stack) {
2868                 
2869                 int i = sym->stack;
2870                 if (i > 256 ) 
2871                         werror(W_STACK_OVERFLOW,sym->name);
2872                 
2873                 if (i > 3 && sym->recvSize < 4) {                
2874                         
2875                         pic14_emitcode ("mov","a,sp");
2876                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
2877                         pic14_emitcode ("mov","sp,a");
2878                         
2879                 }
2880                 else
2881                         while(i--)
2882                                 pic14_emitcode("inc","sp");
2883         }
2884         
2885         if (sym->xstack) {
2886                 
2887                 pic14_emitcode ("mov","a,_spx");
2888                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
2889                 pic14_emitcode ("mov","_spx,a");
2890         }
2891         
2892 }
2893
2894 /*-----------------------------------------------------------------*/
2895 /* genEndFunction - generates epilogue for functions                       */
2896 /*-----------------------------------------------------------------*/
2897 static void genEndFunction (iCode *ic)
2898 {
2899         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
2900         
2901         FENTRY;
2902
2903         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2904         
2905         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
2906         {
2907                 pic14_emitcode ("mov","%s,_bp",spname);
2908         }
2909         
2910         /* if use external stack but some variables were
2911         added to the local stack then decrement the
2912         local stack */
2913         if (options.useXstack && sym->stack) {    
2914                 pic14_emitcode("mov","a,sp");
2915                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
2916                 pic14_emitcode("mov","sp,a");
2917         }
2918         
2919         
2920         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
2921                 if (options.useXstack) {
2922                         pic14_emitcode("mov","r0,%s",spname);
2923                         pic14_emitcode("movx","a,@r0");
2924                         pic14_emitcode("mov","_bp,a");
2925                         pic14_emitcode("dec","%s",spname);
2926                 }
2927                 else
2928                 {
2929                         pic14_emitcode ("pop","_bp");
2930                 }
2931         }
2932         
2933         /* restore the register bank    */        
2934         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
2935                 pic14_emitcode ("pop","psw");
2936         
2937         if (IFFUNC_ISISR(sym->type)) {
2938                 
2939                 /* now we need to restore the registers */
2940                 /* if this isr has no bank i.e. is going to
2941                 run with bank 0 , then we need to save more
2942 registers :-) */
2943                 if (!FUNC_REGBANK(sym->type)) {
2944                         
2945                 /* if this function does not call any other
2946                 function then we can be economical and
2947                         save only those registers that are used */
2948                         if (! IFFUNC_HASFCALL(sym->type)) {
2949                                 int i;
2950                                 
2951                                 /* if any registers used */
2952                                 if (sym->regsUsed) {
2953                                         /* save the registers used */
2954                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
2955                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2956                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2957                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
2958                                         }
2959                                 }
2960                                 
2961                         } else {
2962                         /* this function has    a function call cannot
2963                         determines register usage so we will have the
2964                                 entire bank */
2965                                 unsaverbank(0,ic,FALSE);
2966                         }       
2967                 }
2968 #if 0
2969                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2970                 {
2971                         if (options.stack10bit)
2972                         {
2973                                 pic14_emitcode ("pop", "dpx1");
2974                                 pic14_emitcode ("pop", "dph1");
2975                                 pic14_emitcode ("pop", "dpl1");
2976                         } 
2977                         pic14_emitcode ("pop", "dps");
2978                         pic14_emitcode ("pop", "dpx");
2979                 }
2980                 if (!inExcludeList("dph"))
2981                         pic14_emitcode ("pop","dph");
2982                 if (!inExcludeList("dpl"))
2983                         pic14_emitcode ("pop","dpl");
2984                 if (!inExcludeList("b"))
2985                         pic14_emitcode ("pop","b");
2986                 if (!inExcludeList("acc"))
2987                         pic14_emitcode ("pop","acc");
2988                 
2989                 if (IFFUNC_ISCRITICAL(sym->type))
2990                         pic14_emitcode("setb","ea");
2991 #endif
2992                 
2993                 /* if debug then send end of function */
2994                 /*      if (options.debug && currFunc) { */
2995                 if (currFunc) {
2996                         debugFile->writeEndFunction (currFunc, ic, 1);
2997                 }
2998                 
2999                 pic14_emitcode ("reti","");
3000                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3001                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3002                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3003                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3004                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3005                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3006                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3007                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3008                 emitpcodeNULLop(POC_RETFIE);
3009         }
3010         else {
3011                 if (IFFUNC_ISCRITICAL(sym->type))
3012                         pic14_emitcode("setb","ea");
3013                 
3014                 if (IFFUNC_CALLEESAVES(sym->type)) {
3015                         int i;
3016                         
3017                         /* if any registers used */
3018                         if (sym->regsUsed) {
3019                                 /* save the registers used */
3020                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3021                                         if (bitVectBitValue(sym->regsUsed,i) ||
3022                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3023                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3024                                 }
3025                         }
3026                         
3027                 }
3028                 
3029                 /* if debug then send end of function */
3030                 if (currFunc) {
3031                         debugFile->writeEndFunction (currFunc, ic, 1);
3032                 }
3033                 
3034                 pic14_emitcode ("return","");
3035                 emitpcodeNULLop(POC_RETURN);
3036                 
3037                 /* Mark the end of a function */
3038                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3039         }
3040         
3041 }
3042
3043 /*-----------------------------------------------------------------*/
3044 /* genRet - generate code for return statement                                     */
3045 /*-----------------------------------------------------------------*/
3046 static void genRet (iCode *ic)
3047 {
3048         int size,offset = 0 , pushed = 0;
3049         
3050         FENTRY;
3051
3052         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3053         /* if we have no return value then
3054         just generate the "ret" */
3055         if (!IC_LEFT(ic)) 
3056                 goto jumpret;           
3057         
3058                 /* we have something to return then
3059         move the return value into place */
3060         aopOp(IC_LEFT(ic),ic,FALSE);
3061         size = AOP_SIZE(IC_LEFT(ic));
3062         
3063         while (size--) {
3064                 char *l ;
3065                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3066                         /* #NOCHANGE */
3067                         l = aopGet(AOP(IC_LEFT(ic)),offset++,
3068                                 FALSE,TRUE);
3069                         pic14_emitcode("push","%s",l);
3070                         pushed++;
3071                 } else {
3072                         l = aopGet(AOP(IC_LEFT(ic)),offset,
3073                                 FALSE,FALSE);
3074                         if (strcmp(fReturn[offset],l)) {
3075                                 if ((((AOP(IC_LEFT(ic))->type) == AOP_PCODE) && 
3076                                         AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE) ||
3077                                         ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3078                                         ( (AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3079                                         emitpcode(POC_MOVLW, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
3080                                 }else {
3081                                         emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset));
3082                                 }
3083                                 if(size) {
3084                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr+1-size));
3085                                 }
3086                                 offset++;
3087                         }
3088                 }
3089         }
3090         
3091         if (pushed) {
3092                 while(pushed) {
3093                         pushed--;
3094                         if (strcmp(fReturn[pushed],"a"))
3095                                 pic14_emitcode("pop",fReturn[pushed]);
3096                         else
3097                                 pic14_emitcode("pop","acc");
3098                 }
3099         }
3100         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3101         
3102 jumpret:
3103         /* generate a jump to the return label
3104         if the next is not the return statement */
3105         if (!(ic->next && ic->next->op == LABEL &&
3106                 IC_LABEL(ic->next) == returnLabel)) {
3107                 
3108                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3109                 pic14_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3110         }
3111         
3112 }
3113
3114 /*-----------------------------------------------------------------*/
3115 /* genLabel - generates a label                                                                    */
3116 /*-----------------------------------------------------------------*/
3117 static void genLabel (iCode *ic)
3118 {
3119         FENTRY;
3120
3121         /* special case never generate */
3122         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3123         if (IC_LABEL(ic) == entryLabel)
3124                 return ;
3125         
3126         emitpLabel(IC_LABEL(ic)->key);
3127         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3128 }
3129
3130 /*-----------------------------------------------------------------*/
3131 /* genGoto - generates a goto                                                                      */
3132 /*-----------------------------------------------------------------*/
3133 //tsd
3134 static void genGoto (iCode *ic)
3135 {
3136         FENTRY;
3137
3138         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3139         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3140 }
3141
3142
3143 /*-----------------------------------------------------------------*/
3144 /* genMultbits :- multiplication of bits                                                   */
3145 /*-----------------------------------------------------------------*/
3146 static void genMultbits (operand *left, 
3147                                                  operand *right, 
3148                                                  operand *result)
3149 {
3150         FENTRY;
3151         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3152         
3153         if(!pic14_sameRegs(AOP(result),AOP(right)))
3154                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3155         
3156         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3157         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3158         emitpcode(POC_BCF,  popGet(AOP(result),0));
3159         
3160 }
3161
3162
3163 /*-----------------------------------------------------------------*/
3164 /* genMultOneByte : 8 bit multiplication & division                        */
3165 /*-----------------------------------------------------------------*/
3166 static void genMultOneByte (operand *left,
3167                                                         operand *right,
3168                                                         operand *result)
3169 {
3170         sym_link *opetype = operandType(result);
3171         
3172         // symbol *lbl ;
3173         int size,offset;
3174         
3175         FENTRY;
3176         
3177         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3178         DEBUGpic14_AopType(__LINE__,left,right,result);
3179         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3180         
3181         /* (if two literals, the value is computed before) */
3182         /* if one literal, literal on the right */
3183         if (AOP_TYPE(left) == AOP_LIT){
3184                 operand *t = right;
3185                 right = left;
3186                 left = t;
3187         }
3188         
3189         size = AOP_SIZE(result);
3190         if(size == 1) {
3191                 
3192                 if (AOP_TYPE(right) == AOP_LIT){
3193                         pic14_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3194                                 aopGet(AOP(right),0,FALSE,FALSE), 
3195                                 aopGet(AOP(left),0,FALSE,FALSE), 
3196                                 aopGet(AOP(result),0,FALSE,FALSE));
3197                         pic14_emitcode("call","genMultLit");
3198                 } else {
3199                         pic14_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3200                                 aopGet(AOP(right),0,FALSE,FALSE), 
3201                                 aopGet(AOP(left),0,FALSE,FALSE), 
3202                                 aopGet(AOP(result),0,FALSE,FALSE));
3203                         pic14_emitcode("call","genMult8X8_8");
3204                         
3205                 }
3206                 genMult8X8_8 (left, right,result);
3207                 
3208                 
3209                 /* signed or unsigned */
3210                 //pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3211                 //l = aopGet(AOP(left),0,FALSE,FALSE);
3212                 //MOVA(l);               
3213                 //pic14_emitcode("mul","ab");
3214                 /* if result size = 1, mul signed = mul unsigned */
3215                 //aopPut(AOP(result),"a",0);
3216                 
3217         } else {        // (size > 1)
3218                 
3219                 pic14_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3220                         aopGet(AOP(right),0,FALSE,FALSE), 
3221                         aopGet(AOP(left),0,FALSE,FALSE), 
3222                         aopGet(AOP(result),0,FALSE,FALSE));
3223                 
3224                 if (SPEC_USIGN(opetype)){
3225                         pic14_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3226                         genUMult8X8_16 (left, right, result, NULL);
3227                         
3228                         if (size > 2) {
3229                                 /* for filling the MSBs */
3230                                 emitpcode(POC_CLRF,  popGet(AOP(result),2));
3231                                 emitpcode(POC_CLRF,  popGet(AOP(result),3));
3232                         }
3233                 }
3234                 else{
3235                         pic14_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3236                         
3237                         pic14_emitcode("mov","a,b");
3238                         
3239                         /* adjust the MSB if left or right neg */
3240                         
3241                         /* if one literal */
3242                         if (AOP_TYPE(right) == AOP_LIT){
3243                                 pic14_emitcode("multiply ","right is a lit");
3244                                 /* AND literal negative */
3245                                 if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3246                                         /* adjust MSB (c==0 after mul) */
3247                                         pic14_emitcode("subb","a,%s", aopGet(AOP(left),0,FALSE,FALSE));
3248                                 }
3249                         }
3250                         else{
3251                                 genSMult8X8_16 (left, right, result, NULL);
3252                         }
3253                         
3254                         if(size > 2){
3255                                 pic14_emitcode("multiply ","size is greater than 2, so propogate sign");
3256                                 /* get the sign */
3257                                 pic14_emitcode("rlc","a");
3258                                 pic14_emitcode("subb","a,acc");
3259                         }
3260                 }
3261                 
3262                 size -= 2;
3263                 offset = 2;
3264                 if (size > 0)
3265                         while (size--)
3266                                 pic14_emitcode("multiply ","size is way greater than 2, so propogate sign");
3267                         //aopPut(AOP(result),"a",offset++);
3268         }
3269 }
3270
3271 /*-----------------------------------------------------------------*/
3272 /* genMult - generates code for multiplication                                     */
3273 /*-----------------------------------------------------------------*/
3274 static void genMult (iCode *ic)
3275 {
3276         operand *left = IC_LEFT(ic);
3277         operand *right = IC_RIGHT(ic);
3278         operand *result= IC_RESULT(ic); 
3279         
3280         FENTRY;
3281
3282         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3283         /* assign the amsops */
3284         aopOp (left,ic,FALSE);
3285         aopOp (right,ic,FALSE);
3286         aopOp (result,ic,TRUE);
3287         
3288         DEBUGpic14_AopType(__LINE__,left,right,result);
3289         
3290         /* special cases first */
3291         /* both are bits */
3292         if (AOP_TYPE(left) == AOP_CRY &&
3293                 AOP_TYPE(right)== AOP_CRY) {
3294                 genMultbits(left,right,result);
3295                 goto release ;
3296         }
3297         
3298         /* if both are of size == 1 */
3299         if (AOP_SIZE(left) == 1 &&
3300                 AOP_SIZE(right) == 1 ) {
3301                 genMultOneByte(left,right,result);
3302                 goto release ;
3303         }
3304         
3305         pic14_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3306
3307         assert( AOP_SIZE(left) == AOP_SIZE(right) );
3308         assert( AOP_SIZE(result) >= AOP_SIZE(left) );
3309
3310         /* should have been converted to function call */
3311         assert(0) ;
3312         
3313 release :
3314         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3315         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3316         freeAsmop(result,NULL,ic,TRUE); 
3317 }
3318
3319 /*-----------------------------------------------------------------*/
3320 /* genDivbits :- division of bits                                                                  */
3321 /*-----------------------------------------------------------------*/
3322 static void genDivbits (operand *left, 
3323                                                 operand *right, 
3324                                                 operand *result)
3325 {
3326         
3327         char *l;
3328         
3329         FENTRY;
3330
3331         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3332         /* the result must be bit */      
3333         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3334         l = aopGet(AOP(left),0,FALSE,FALSE);
3335         
3336         MOVA(l);          
3337         
3338         pic14_emitcode("div","ab");
3339         pic14_emitcode("rrc","a");
3340         aopPut(AOP(result),"c",0);
3341 }
3342
3343 /*-----------------------------------------------------------------*/
3344 /* genDivOneByte : 8 bit division                                                                  */
3345 /*-----------------------------------------------------------------*/
3346 static void genDivOneByte (operand *left,
3347                                                    operand *right,
3348                                                    operand *result)
3349 {
3350         sym_link *opetype = operandType(result);
3351         char *l ;
3352         symbol *lbl ;
3353         int size,offset;
3354         
3355         FENTRY;
3356         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3357         size = AOP_SIZE(result) - 1;
3358         offset = 1;
3359         /* signed or unsigned */
3360         if (SPEC_USIGN(opetype)) {
3361                 /* unsigned is easy */
3362                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3363                 l = aopGet(AOP(left),0,FALSE,FALSE);
3364                 MOVA(l);                
3365                 pic14_emitcode("div","ab");
3366                 aopPut(AOP(result),"a",0);
3367                 while (size--)
3368                         aopPut(AOP(result),zero,offset++);
3369                 return ;
3370         }
3371         
3372         /* signed is a little bit more difficult */
3373         
3374         /* save the signs of the operands */
3375         l = aopGet(AOP(left),0,FALSE,FALSE);      
3376         MOVA(l);          
3377         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3378         pic14_emitcode("push","acc"); /* save it on the stack */
3379         
3380         /* now sign adjust for both left & right */
3381         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3382         MOVA(l);                 
3383         lbl = newiTempLabel(NULL);
3384         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3385         pic14_emitcode("cpl","a");   
3386         pic14_emitcode("inc","a");
3387         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3388         pic14_emitcode("mov","b,a");
3389         
3390         /* sign adjust left side */
3391         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3392         MOVA(l);
3393         
3394         lbl = newiTempLabel(NULL);
3395         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3396         pic14_emitcode("cpl","a");
3397         pic14_emitcode("inc","a");
3398         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3399         
3400         /* now the division */
3401         pic14_emitcode("div","ab");
3402         /* we are interested in the lower order
3403         only */
3404         pic14_emitcode("mov","b,a");
3405         lbl = newiTempLabel(NULL);
3406         pic14_emitcode("pop","acc");     
3407         /* if there was an over flow we don't 
3408         adjust the sign of the result */
3409         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3410         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3411         CLRC;
3412         pic14_emitcode("clr","a");
3413         pic14_emitcode("subb","a,b");
3414         pic14_emitcode("mov","b,a");
3415         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3416         
3417         /* now we are done */
3418         aopPut(AOP(result),"b",0);
3419         if(size > 0){
3420                 pic14_emitcode("mov","c,b.7");
3421                 pic14_emitcode("subb","a,acc");   
3422         }
3423         while (size--)
3424                 aopPut(AOP(result),"a",offset++);
3425         
3426 }
3427
3428 /*-----------------------------------------------------------------*/
3429 /* genDiv - generates code for division                                                    */
3430 /*-----------------------------------------------------------------*/
3431 static void genDiv (iCode *ic)
3432 {
3433         operand *left = IC_LEFT(ic);
3434         operand *right = IC_RIGHT(ic);
3435         operand *result= IC_RESULT(ic); 
3436         
3437         FENTRY;
3438         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3439         /* assign the amsops */
3440         aopOp (left,ic,FALSE);
3441         aopOp (right,ic,FALSE);
3442         aopOp (result,ic,TRUE);
3443         
3444         /* special cases first */
3445         /* both are bits */
3446         if (AOP_TYPE(left) == AOP_CRY &&
3447                 AOP_TYPE(right)== AOP_CRY) {
3448                 genDivbits(left,right,result);
3449                 goto release ;
3450         }
3451         
3452         /* if both are of size == 1 */
3453         if (AOP_SIZE(left) == 1 &&
3454                 AOP_SIZE(right) == 1 ) {
3455                 genDivOneByte(left,right,result);
3456                 goto release ;
3457         }
3458         
3459         /* should have been converted to function call */
3460         assert(0);
3461 release :
3462         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3463         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3464         freeAsmop(result,NULL,ic,TRUE); 
3465 }
3466
3467 /*-----------------------------------------------------------------*/
3468 /* genModbits :- modulus of bits                                                                   */
3469 /*-----------------------------------------------------------------*/
3470 static void genModbits (operand *left, 
3471                                                 operand *right, 
3472                                                 operand *result)
3473 {
3474         
3475         char *l;
3476         
3477         FENTRY;
3478         /* the result must be bit */      
3479         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3480         l = aopGet(AOP(left),0,FALSE,FALSE);
3481         
3482         MOVA(l);
3483         
3484         pic14_emitcode("div","ab");
3485         pic14_emitcode("mov","a,b");
3486         pic14_emitcode("rrc","a");
3487         aopPut(AOP(result),"c",0);
3488 }
3489
3490 /*-----------------------------------------------------------------*/
3491 /* genModOneByte : 8 bit modulus                                                                   */
3492 /*-----------------------------------------------------------------*/
3493 static void genModOneByte (operand *left,
3494                                                    operand *right,
3495                                                    operand *result)
3496 {
3497         sym_link *opetype = operandType(result);
3498         char *l ;
3499         symbol *lbl ;
3500         
3501         FENTRY;
3502         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3503         /* signed or unsigned */
3504         if (SPEC_USIGN(opetype)) {
3505                 /* unsigned is easy */
3506                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3507                 l = aopGet(AOP(left),0,FALSE,FALSE);
3508                 MOVA(l);        
3509                 pic14_emitcode("div","ab");
3510                 aopPut(AOP(result),"b",0);
3511                 return ;
3512         }
3513         
3514         /* signed is a little bit more difficult */
3515         
3516         /* save the signs of the operands */
3517         l = aopGet(AOP(left),0,FALSE,FALSE);      
3518         MOVA(l);
3519         
3520         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3521         pic14_emitcode("push","acc"); /* save it on the stack */
3522         
3523         /* now sign adjust for both left & right */
3524         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3525         MOVA(l);
3526         
3527         lbl = newiTempLabel(NULL);
3528         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3529         pic14_emitcode("cpl","a");   
3530         pic14_emitcode("inc","a");
3531         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3532         pic14_emitcode("mov","b,a"); 
3533         
3534         /* sign adjust left side */
3535         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3536         MOVA(l);
3537         
3538         lbl = newiTempLabel(NULL);
3539         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3540         pic14_emitcode("cpl","a");   
3541         pic14_emitcode("inc","a");
3542         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3543         
3544         /* now the multiplication */
3545         pic14_emitcode("div","ab");
3546         /* we are interested in the lower order
3547         only */
3548         lbl = newiTempLabel(NULL);
3549         pic14_emitcode("pop","acc");     
3550         /* if there was an over flow we don't 
3551         adjust the sign of the result */
3552         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3553         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3554         CLRC ;
3555         pic14_emitcode("clr","a");
3556         pic14_emitcode("subb","a,b");
3557         pic14_emitcode("mov","b,a");
3558         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3559         
3560         /* now we are done */
3561         aopPut(AOP(result),"b",0);
3562         
3563 }
3564
3565 /*-----------------------------------------------------------------*/
3566 /* genMod - generates code for division                                                    */
3567 /*-----------------------------------------------------------------*/
3568 static void genMod (iCode *ic)
3569 {
3570         operand *left = IC_LEFT(ic);
3571         operand *right = IC_RIGHT(ic);
3572         operand *result= IC_RESULT(ic);  
3573         
3574         FENTRY;
3575         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3576         /* assign the amsops */
3577         aopOp (left,ic,FALSE);
3578         aopOp (right,ic,FALSE);
3579         aopOp (result,ic,TRUE);
3580         
3581         /* special cases first */
3582         /* both are bits */
3583         if (AOP_TYPE(left) == AOP_CRY &&
3584                 AOP_TYPE(right)== AOP_CRY) {
3585                 genModbits(left,right,result);
3586                 goto release ;
3587         }
3588         
3589         /* if both are of size == 1 */
3590         if (AOP_SIZE(left) == 1 &&
3591                 AOP_SIZE(right) == 1 ) {
3592                 genModOneByte(left,right,result);
3593                 goto release ;
3594         }
3595         
3596         /* should have been converted to function call */
3597         assert(0);
3598         
3599 release :
3600         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3601         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3602         freeAsmop(result,NULL,ic,TRUE); 
3603 }
3604
3605 /*-----------------------------------------------------------------*/
3606 /* genIfxJump :- will create a jump depending on the ifx                   */
3607 /*-----------------------------------------------------------------*/
3608 /*
3609 note: May need to add parameter to indicate when a variable is in bit space.
3610 */
3611 static void genIfxJump (iCode *ic, char *jval)
3612 {
3613         
3614         FENTRY;
3615         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3616         /* if true label then we jump if condition
3617         supplied is true */
3618         if ( IC_TRUE(ic) ) {
3619                 
3620                 if(strcmp(jval,"a") == 0)
3621                         emitSKPZ;
3622                 else if (strcmp(jval,"c") == 0)
3623                         emitSKPC;
3624                 else {
3625                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3626                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3627                 }
3628                 
3629                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3630                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3631                 
3632         }
3633         else {
3634                 /* false label is present */
3635                 if(strcmp(jval,"a") == 0)
3636                         emitSKPNZ;
3637                 else if (strcmp(jval,"c") == 0)
3638                         emitSKPNC;
3639                 else {
3640                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3641                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3642                 }
3643                 
3644                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3645                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3646                 
3647         }
3648         
3649         
3650         /* mark the icode as generated */
3651         ic->generated = 1;
3652 }
3653
3654 /*-----------------------------------------------------------------*/
3655 /* genSkip                                                                                                                 */
3656 /*-----------------------------------------------------------------*/
3657 static void genSkip(iCode *ifx,int status_bit)
3658 {
3659         FENTRY;
3660         if(!ifx)
3661                 return;
3662         
3663         if ( IC_TRUE(ifx) ) {
3664                 switch(status_bit) {
3665                 case 'z':
3666                         emitSKPNZ;
3667                         break;
3668                         
3669                 case 'c':
3670                         emitSKPNC;
3671                         break;
3672                         
3673                 case 'd':
3674                         emitSKPDC;
3675                         break;
3676                         
3677                 }
3678                 
3679                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3680                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3681                 
3682         } else {
3683                 
3684                 switch(status_bit) {
3685                         
3686                 case 'z':
3687                         emitSKPZ;
3688                         break;
3689                         
3690                 case 'c':
3691                         emitSKPC;
3692                         break;
3693                         
3694                 case 'd':
3695                         emitSKPDC;
3696                         break;
3697                 }
3698                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3699                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3700                 
3701         }
3702         
3703 }
3704
3705 /*-----------------------------------------------------------------*/
3706 /* genSkipc                                                                                                        */
3707 /*-----------------------------------------------------------------*/
3708 static void genSkipc(resolvedIfx *rifx)
3709 {
3710         FENTRY;
3711         if(!rifx)
3712                 return;
3713         
3714         if(rifx->condition)
3715                 emitSKPNC;
3716         else
3717                 emitSKPC;
3718         
3719         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3720         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3721         rifx->generated = 1;
3722 }
3723
3724 /*-----------------------------------------------------------------*/
3725 /* genSkipz2                                                                                                       */
3726 /*-----------------------------------------------------------------*/
3727 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3728 {
3729         FENTRY;
3730         if(!rifx)
3731                 return;
3732         
3733         if( (rifx->condition ^ invert_condition) & 1)
3734                 emitSKPZ;
3735         else
3736                 emitSKPNZ;
3737         
3738         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3739         rifx->generated = 1;
3740 }
3741
3742 /*-----------------------------------------------------------------*/
3743 /* genSkipz                                                        */
3744 /*-----------------------------------------------------------------*/
3745 static void genSkipz(iCode *ifx, int condition)
3746 {
3747         FENTRY;
3748         if(!ifx)
3749                 return;
3750         
3751         if(condition)
3752                 emitSKPNZ;
3753         else
3754                 emitSKPZ;
3755         
3756         if ( IC_TRUE(ifx) )
3757                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3758         else
3759                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3760         
3761         if ( IC_TRUE(ifx) )
3762                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3763         else
3764                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3765         
3766 }
3767
3768 #if 0
3769 /*-----------------------------------------------------------------*/
3770 /* genSkipCond                                                     */
3771 /*-----------------------------------------------------------------*/
3772 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3773 {
3774         FENTRY;
3775         if(!rifx)
3776                 return;
3777         
3778         if(rifx->condition)
3779                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3780         else
3781                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3782         
3783         
3784         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3785         rifx->generated = 1;
3786 }
3787 #endif
3788
3789 #if 0
3790 /*-----------------------------------------------------------------*/
3791 /* genChkZeroes :- greater or less than comparison                 */
3792 /*     For each byte in a literal that is zero, inclusive or the   */
3793 /*     the corresponding byte in the operand with W                */
3794 /*     returns true if any of the bytes are zero                   */
3795 /*-----------------------------------------------------------------*/
3796 static int genChkZeroes(operand *op, int lit,  int size)
3797 {
3798         
3799         int i;
3800         int flag =1;
3801         
3802         while(size--) {
3803                 i = (lit >> (size*8)) & 0xff;
3804                 
3805                 if(i==0) {
3806                         if(flag) 
3807                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3808                         else
3809                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3810                         flag = 0;
3811                 }
3812         }
3813         
3814         return (flag==0);
3815 }
3816 #endif
3817
3818
3819 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3820 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3821 #define DEBUGpc           emitpComment
3822
3823 /*-----------------------------------------------------------------*/
3824 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3825 /*                  aop (if it's NOT a literal) or from lit (if    */
3826 /*                  aop is a literal)                              */
3827 /*-----------------------------------------------------------------*/
3828 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3829   if (aop->type == AOP_LIT) {
3830     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3831   } else {
3832     emitpcode (POC_MOVFW, popGet (aop, offset));
3833   }
3834 }
3835
3836 /* genCmp performs a left < right comparison, stores
3837  * the outcome in result (if != NULL) and generates
3838  * control flow code for the ifx (if != NULL).
3839  *
3840  * This version leaves in sequences like
3841  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3842  * which should be optmized by the peephole
3843  * optimizer - RN 2005-01-01 */
3844 static void genCmp (operand *left,operand *right,
3845                     operand *result, iCode *ifx, int sign)
3846 {
3847   resolvedIfx rIfx;
3848   int size;
3849   int offs;
3850   symbol *templbl;
3851   operand *dummy;
3852   unsigned long lit;
3853   unsigned long mask;
3854   int performedLt;
3855   int invert_result = 0;
3856
3857   FENTRY;
3858   
3859   assert (AOP_SIZE(left) == AOP_SIZE(right));
3860   assert (left && right);
3861
3862   size = AOP_SIZE(right) - 1;
3863   mask = (0x100UL << (size*8)) - 1;
3864   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3865   performedLt = 1;
3866   templbl = NULL;
3867   lit = 0;
3868   
3869   resolveIfx (&rIfx, ifx);
3870
3871   /**********************************************************************
3872    * handle bits - bit compares are promoted to int compares seemingly! *
3873    **********************************************************************/
3874 #if 0
3875   // THIS IS COMPLETELY UNTESTED!
3876   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3877     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3878     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3879     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3880
3881     emitSETC;
3882     // 1 < {0,1} is false --> clear C by skipping the next instruction
3883     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3884     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3885     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3886     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3887     emitCLRC; // only skipped for left=0 && right=1
3888
3889     goto correct_result_in_carry;
3890   } // if
3891 #endif
3892
3893   /*************************************************
3894    * make sure that left is register (or the like) *
3895    *************************************************/
3896   if (!isAOP_REGlike(left)) {
3897     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3898     assert (isAOP_LIT(left));
3899     assert (isAOP_REGlike(right));
3900     // swap left and right
3901     // left < right <==> right > left <==> (right >= left + 1)
3902     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3903
3904     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3905       // MAXVALUE < right? always false
3906       if (performedLt) emitCLRC; else emitSETC;
3907       goto correct_result_in_carry;
3908     } // if
3909
3910     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3911     // that's why we handled it above.
3912     lit++;
3913
3914     dummy = left;
3915     left = right;
3916     right = dummy;
3917
3918     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3919   } else if (isAOP_LIT(right)) {
3920     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3921   } // if
3922
3923   assert (isAOP_REGlike(left)); // left must be register or the like
3924   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3925
3926   /*************************************************
3927    * special cases go here                         *
3928    *************************************************/
3929
3930   if (isAOP_LIT(right)) {
3931     if (!sign) {
3932       // unsigned comparison to a literal
3933       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3934       if (lit == 0) {
3935         // unsigned left < 0? always false
3936         if (performedLt) emitCLRC; else emitSETC;
3937         goto correct_result_in_carry;
3938       }
3939     } else {
3940       // signed comparison to a literal
3941       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3942       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3943         // signed left < 0x80000000? always false
3944         if (performedLt) emitCLRC; else emitSETC;
3945         goto correct_result_in_carry;
3946       } else if (lit == 0) {
3947         // compare left < 0; set CARRY if SIGNBIT(left) is set
3948         if (performedLt) emitSETC; else emitCLRC;
3949         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3950         if (performedLt) emitCLRC; else emitSETC;
3951         goto correct_result_in_carry;
3952       }
3953     } // if (!sign)
3954   } // right is literal
3955
3956   /*************************************************
3957    * perform a general case comparison             *
3958    * make sure we get CARRY==1 <==> left >= right  *
3959    *************************************************/
3960   // compare most significant bytes
3961   //DEBUGpc ("comparing bytes at offset %d", size);
3962   if (!sign) {
3963     // unsigned comparison
3964     pic14_mov2w_regOrLit (AOP(right), lit, size);
3965     emitpcode (POC_SUBFW, popGet (AOP(left), size));
3966   } else {
3967     // signed comparison
3968     // (add 2^n to both operands then perform an unsigned comparison)
3969     if (isAOP_LIT(right)) {
3970       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3971       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3972
3973       if (litbyte == 0x80) {
3974         // left >= 0x80 -- always true, but more bytes to come
3975         mov2w (AOP(left), size);
3976         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3977         emitSETC;
3978       } else {
3979         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3980         mov2w (AOP(left), size);
3981         emitpcode (POC_ADDLW, popGetLit (0x80));
3982         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3983       } // if
3984     } else {
3985       pCodeOp *pctemp = popGetTempReg();
3986       mov2w (AOP(left), size);
3987       emitpcode (POC_ADDLW, popGetLit (0x80));
3988       emitpcode (POC_MOVWF, pctemp);
3989       mov2w (AOP(right), size);
3990       emitpcode (POC_ADDLW, popGetLit (0x80));
3991       emitpcode (POC_SUBFW, pctemp);
3992       popReleaseTempReg(pctemp);
3993     }
3994   } // if (!sign)
3995
3996   // compare remaining bytes (treat as unsigned case from above)
3997   templbl = newiTempLabel ( NULL );
3998   offs = size;
3999   while (offs--) {
4000     //DEBUGpc ("comparing bytes at offset %d", offs);
4001     emitSKPZ;
4002     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4003     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4004     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4005   } // while (offs)
4006   emitpLabel (templbl->key);
4007   goto result_in_carry;
4008
4009 result_in_carry:
4010   
4011   /****************************************************
4012    * now CARRY contains the result of the comparison: *
4013    * SUBWF sets CARRY iff                             *
4014    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4015    * (F=left, W=right)                                *
4016    ****************************************************/
4017
4018   if (performedLt) {
4019     invert_result = 1;
4020     // value will be used in the following genSkipc()
4021     rIfx.condition ^= 1;
4022   } // if
4023
4024 correct_result_in_carry:
4025
4026   // assign result to variable (if neccessary)
4027   if (result && AOP_TYPE(result) != AOP_CRY) {
4028     //DEBUGpc ("assign result");
4029     size = AOP_SIZE(result);
4030     while (size--) {
4031       emitpcode (POC_CLRF, popGet (AOP(result), size));
4032     } // while
4033     if (invert_result) {
4034       emitSKPC;
4035       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4036     } else {
4037       emitpcode (POC_RLF, popGet (AOP(result), 0));
4038     }
4039   } // if (result)
4040
4041   // perform conditional jump
4042   if (ifx) {
4043     //DEBUGpc ("generate control flow");
4044     genSkipc (&rIfx);
4045     ifx->generated = 1;
4046   } // if
4047 }
4048
4049
4050 #if 0
4051 /* OLD VERSION -- BUGGY, DO NOT USE */
4052
4053 /*-----------------------------------------------------------------*/
4054 /* genCmp :- greater or less than comparison                       */
4055 /*-----------------------------------------------------------------*/
4056 static void genCmp (operand *left,operand *right,
4057                                         operand *result, iCode *ifx, int sign)
4058 {
4059         int size; //, offset = 0 ;
4060         unsigned long lit = 0L,i = 0;
4061         resolvedIfx rFalseIfx;
4062         //  resolvedIfx rTrueIfx;
4063         symbol *truelbl;
4064
4065         FENTRY;
4066         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4067         /*
4068         if(ifx) {
4069         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4070         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4071         }
4072         */
4073         
4074         resolveIfx(&rFalseIfx,ifx);
4075         truelbl  = newiTempLabel(NULL);
4076         size = max(AOP_SIZE(left),AOP_SIZE(right));
4077         
4078         DEBUGpic14_AopType(__LINE__,left,right,result);
4079         
4080 #define _swapp
4081         
4082         /* if literal is on the right then swap with left */
4083         if ((AOP_TYPE(right) == AOP_LIT)) {
4084                 operand *tmp = right ;
4085                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4086                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4087 #ifdef _swapp
4088                 
4089                 lit = (lit - 1) & mask;
4090                 right = left;
4091                 left = tmp;
4092                 rFalseIfx.condition ^= 1;
4093 #endif
4094                 
4095         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4096                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4097         }
4098         
4099         
4100         //if(IC_TRUE(ifx) == NULL)
4101         /* if left & right are bit variables */
4102         if (AOP_TYPE(left) == AOP_CRY &&
4103                 AOP_TYPE(right) == AOP_CRY ) {
4104                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4105                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4106         } else {
4107         /* subtract right from left if at the
4108         end the carry flag is set then we know that
4109                 left is greater than right */
4110                 
4111                 symbol *lbl  = newiTempLabel(NULL);
4112                 
4113 #ifndef _swapp
4114                 if(AOP_TYPE(right) == AOP_LIT) {
4115                         
4116                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4117                         
4118                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4119                         
4120                         /* special cases */
4121                         
4122                         if(lit == 0) {
4123                                 
4124                                 if(sign != 0) 
4125                                         genSkipCond(&rFalseIfx,left,size-1,7);
4126                                 else 
4127                                         /* no need to compare to 0...*/
4128                                         /* NOTE: this is a de-generate compare that most certainly 
4129                                         *       creates some dead code. */
4130                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4131                                 
4132                                 if(ifx) ifx->generated = 1;
4133                                 return;
4134                                 
4135                         }
4136                         size--;
4137                         
4138                         if(size == 0) {
4139                                 //i = (lit >> (size*8)) & 0xff;
4140                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4141                                 
4142                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4143                                 
4144                                 i = ((0-lit) & 0xff);
4145                                 if(sign) {
4146                                         if( i == 0x81) { 
4147                                         /* lit is 0x7f, all signed chars are less than
4148                                                 * this except for 0x7f itself */
4149                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4150                                                 genSkipz2(&rFalseIfx,0);
4151                                         } else {
4152                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4153                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4154                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4155                                         }
4156                                         
4157                                 } else {
4158                                         if(lit == 1) {
4159                                                 genSkipz2(&rFalseIfx,1);
4160                                         } else {
4161                                                 emitpcode(POC_ADDLW, popGetLit(i));
4162                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4163                                         }
4164                                 }
4165                                 
4166                                 if(ifx) ifx->generated = 1;
4167                                 return;
4168                         }
4169                         
4170                         /* chars are out of the way. now do ints and longs */
4171                         
4172                         
4173                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4174                         
4175                         /* special cases */
4176                         
4177                         if(sign) {
4178                                 
4179                                 if(lit == 0) {
4180                                         genSkipCond(&rFalseIfx,left,size,7);
4181                                         if(ifx) ifx->generated = 1;
4182                                         return;
4183                                 }
4184                                 
4185                                 if(lit <0x100) {
4186                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4187                                         
4188                                         //rFalseIfx.condition ^= 1;
4189                                         //genSkipCond(&rFalseIfx,left,size,7);
4190                                         //rFalseIfx.condition ^= 1;
4191                                         
4192                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4193                                         if(rFalseIfx.condition)
4194                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4195                                         else
4196                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4197                                         
4198                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4199                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4200                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4201                                         
4202                                         while(size > 1)
4203                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4204                                         
4205                                         if(rFalseIfx.condition) {
4206                                                 emitSKPZ;
4207                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4208                                                 
4209                                         } else {
4210                                                 emitSKPNZ;
4211                                         }
4212                                         
4213                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4214                                         emitpLabel(truelbl->key);
4215                                         if(ifx) ifx->generated = 1;
4216                                         return;
4217                                         
4218                                 }
4219                                 
4220                                 if(size == 1) {
4221                                         
4222                                         if( (lit & 0xff) == 0) {
4223                                                 /* lower byte is zero */
4224                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4225                                                 i = ((lit >> 8) & 0xff) ^0x80;
4226                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4227                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4228                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4229                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4230                                                 
4231                                                 
4232                                                 if(ifx) ifx->generated = 1;
4233                                                 return;
4234                                                 
4235                                         }
4236                                 } else {
4237                                         /* Special cases for signed longs */
4238                                         if( (lit & 0xffffff) == 0) {
4239                                                 /* lower byte is zero */
4240                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4241                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4242                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4243                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4244                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4245                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4246                                                 
4247                                                 
4248                                                 if(ifx) ifx->generated = 1;
4249                                                 return;
4250                                                 
4251                                         }
4252                                         
4253                                 }
4254                                 
4255                                 
4256                                 if(lit & (0x80 << (size*8))) {
4257                                         /* lit is negative */
4258                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4259                                         
4260                                         //genSkipCond(&rFalseIfx,left,size,7);
4261                                         
4262                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4263                                         
4264                                         if(rFalseIfx.condition)
4265                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4266                                         else
4267                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4268                                         
4269                                         
4270                                 } else {
4271                                         /* lit is positive */
4272                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4273                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4274                                         if(rFalseIfx.condition)
4275                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4276                                         else
4277                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4278                                         
4279                                 }
4280                                 
4281                                 /* There are no more special cases, so perform a general compare */
4282                                 
4283                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4284                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4285                                 
4286                                 while(size--) {
4287                                         
4288                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4289                                         emitSKPNZ;
4290                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4291                                 }
4292                                 //rFalseIfx.condition ^= 1;
4293                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4294                                 
4295                                 emitpLabel(truelbl->key);
4296                                 
4297                                 if(ifx) ifx->generated = 1;
4298                                 return;
4299                                 
4300                                 
4301                         }
4302
4303
4304                         /* sign is out of the way. So now do an unsigned compare */
4305                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4306
4307
4308                         /* General case - compare to an unsigned literal on the right.*/
4309
4310                         i = (lit >> (size*8)) & 0xff;
4311                         emitpcode(POC_MOVLW, popGetLit(i));
4312                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4313                         while(size--) {
4314                                 i = (lit >> (size*8)) & 0xff;
4315                                 
4316                                 if(i) {
4317                                         emitpcode(POC_MOVLW, popGetLit(i));
4318                                         emitSKPNZ;
4319                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4320                                 } else {
4321                                 /* this byte of the lit is zero, 
4322                                         *if it's not the last then OR in the variable */
4323                                         if(size)
4324                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4325                                 }
4326                         }
4327
4328
4329                 emitpLabel(lbl->key);
4330                 //if(emitFinalCheck)
4331                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4332                 if(sign)
4333                         emitpLabel(truelbl->key);
4334
4335                 if(ifx) ifx->generated = 1;
4336                 return;
4337
4338
4339                 }
4340 #endif  // _swapp
4341
4342                 if(AOP_TYPE(left) == AOP_LIT) {
4343                         //symbol *lbl = newiTempLabel(NULL);
4344                         
4345                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4346                         
4347                         
4348                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4349                         
4350                         /* Special cases */
4351                         if((lit == 0) && (sign == 0)){
4352                                 
4353                                 size--;
4354                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4355                                 while(size) 
4356                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4357                                 
4358                                 genSkipz2(&rFalseIfx,0);
4359                                 if(ifx) ifx->generated = 1;
4360                                 return;
4361                         }
4362                         
4363                         if(size==1) {
4364                                 /* Special cases */
4365                                 lit &= 0xff;
4366                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4367                                         /* degenerate compare can never be true */
4368                                         if(rFalseIfx.condition == 0)
4369                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4370                                         
4371                                         if(ifx) ifx->generated = 1;
4372                                         return;
4373                                 }
4374                                 
4375                                 if(sign) {
4376                                         /* signed comparisons to a literal byte */
4377                                         
4378                                         int lp1 = (lit+1) & 0xff;
4379                                         
4380                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4381                                         switch (lp1) {
4382                                         case 0:
4383                                                 rFalseIfx.condition ^= 1;
4384                                                 genSkipCond(&rFalseIfx,right,0,7);
4385                                                 break;
4386                                         case 0x7f:
4387                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4388                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4389                                                 genSkipz2(&rFalseIfx,1);
4390                                                 break;
4391                                         default:
4392                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4393                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4394                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4395                                                 rFalseIfx.condition ^= 1;
4396                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4397                                                 break;
4398                                         }
4399                                         if(ifx) ifx->generated = 1;
4400                                 } else {
4401                                         /* unsigned comparisons to a literal byte */
4402                                         
4403                                         switch(lit & 0xff ) {
4404                                         case 0:
4405                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4406                                                 genSkipz2(&rFalseIfx,0);
4407                                                 if(ifx) ifx->generated = 1;
4408                                                 break;
4409                                         case 0x7f:
4410                                                 genSkipCond(&rFalseIfx,right,0,7);
4411                                                 if(ifx) ifx->generated = 1;
4412                                                 break;
4413                                                 
4414                                         default:
4415                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4416                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4417                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4418                                                 rFalseIfx.condition ^= 1;
4419                                                 if (AOP_TYPE(result) == AOP_CRY) {
4420                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4421                                                         if(ifx) ifx->generated = 1;
4422                                                 } else {
4423                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4424                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4425                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4426                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4427                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4428                                                 }       
4429                                                 break;
4430                                         }
4431                                 }
4432                                 
4433                                 //goto check_carry;
4434                                 return;
4435                                 
4436                         } else {
4437                                 
4438                                 /* Size is greater than 1 */
4439                                 
4440                                 if(sign) {
4441                                         int lp1 = lit+1;
4442                                         
4443                                         size--;
4444                                         
4445                                         if(lp1 == 0) {
4446                                                 /* this means lit = 0xffffffff, or -1 */
4447                                                 
4448                                                 
4449                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4450                                                 rFalseIfx.condition ^= 1;
4451                                                 genSkipCond(&rFalseIfx,right,size,7);
4452                                                 if(ifx) ifx->generated = 1;
4453                                                 return;
4454                                         }
4455                                         
4456                                         if(lit == 0) {
4457                                                 int s = size;
4458                                                 
4459                                                 if(rFalseIfx.condition) {
4460                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4461                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4462                                                 }
4463                                                 
4464                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4465                                                 while(size--)
4466                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4467                                                 
4468                                                 
4469                                                 emitSKPZ;
4470                                                 if(rFalseIfx.condition) {
4471                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4472                                                         emitpLabel(truelbl->key);
4473                                                 }else {
4474                                                         rFalseIfx.condition ^= 1;
4475                                                         genSkipCond(&rFalseIfx,right,s,7);
4476                                                 }
4477                                                 
4478                                                 if(ifx) ifx->generated = 1;
4479                                                 return;
4480                                         }
4481                                         
4482                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4483                                                 /* lower byte of signed word is zero */
4484                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4485                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4486                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4487                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4488                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4489                                                 rFalseIfx.condition ^= 1;
4490                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4491                                                 
4492                                                 
4493                                                 if(ifx) ifx->generated = 1;
4494                                                 return;
4495                                         }
4496                                         
4497                                         if(lit & (0x80 << (size*8))) {
4498                                                 /* Lit is less than zero */
4499                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4500                                                 //rFalseIfx.condition ^= 1;
4501                                                 //genSkipCond(&rFalseIfx,left,size,7);
4502                                                 //rFalseIfx.condition ^= 1;
4503                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4504                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4505                                                 
4506                                                 if(rFalseIfx.condition)
4507                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4508                                                 else
4509                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4510                                                 
4511                                                 
4512                                         } else {
4513                                                 /* Lit is greater than or equal to zero */
4514                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4515                                                 //rFalseIfx.condition ^= 1;
4516                                                 //genSkipCond(&rFalseIfx,right,size,7);
4517                                                 //rFalseIfx.condition ^= 1;
4518                                                 
4519                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4520                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4521                                                 
4522                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4523                                                 if(rFalseIfx.condition)
4524                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4525                                                 else
4526                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4527                                                 
4528                                         }
4529                                         
4530                                         
4531                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4532                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4533                                         
4534                                         while(size--) {
4535                                                 
4536                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4537                                                 emitSKPNZ;
4538                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4539                                         }
4540                                         rFalseIfx.condition ^= 1;
4541                                         //rFalseIfx.condition = 1;
4542                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4543                                         
4544                                         emitpLabel(truelbl->key);
4545                                         
4546                                         if(ifx) ifx->generated = 1;
4547                                         return;
4548                                         // end of if (sign)
4549                                 } else {
4550                                         
4551                                         /* compare word or long to an unsigned literal on the right.*/
4552                                         
4553                                         
4554                                         size--;
4555                                         if(lit < 0xff) {
4556                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4557                                                 switch (lit) {
4558                                                 case 0:
4559                                                         break; /* handled above */
4560                                                 /*
4561                                                 case 0xff:
4562                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4563                                                         while(size--)
4564                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4565                                                         genSkipz2(&rFalseIfx,0);
4566                                                         break;
4567                                                 */
4568                                                 default:
4569                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4570                                                         while(--size)
4571                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4572                                                         
4573                                                         emitSKPZ;
4574                                                         if(rFalseIfx.condition)
4575                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4576                                                         else
4577                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4578                                                         
4579                                                         
4580                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4581                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4582                                                         
4583                                                         rFalseIfx.condition ^= 1;
4584                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4585                                                 }
4586                                                 
4587                                                 emitpLabel(truelbl->key);
4588                                                 
4589                                                 if(ifx) ifx->generated = 1;
4590                                                 return;
4591                                         }
4592                                         
4593                                         
4594                                         lit++;
4595                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4596                                         i = (lit >> (size*8)) & 0xff;
4597                                         
4598                                         emitpcode(POC_MOVLW, popGetLit(i));
4599                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4600                                         
4601                                         while(size--) {
4602                                                 i = (lit >> (size*8)) & 0xff;
4603                                                 
4604                                                 if(i) {
4605                                                         emitpcode(POC_MOVLW, popGetLit(i));
4606                                                         emitSKPNZ;
4607                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4608                                                 } else {
4609                                                 /* this byte of the lit is zero, 
4610                                                         *if it's not the last then OR in the variable */
4611                                                         if(size)
4612                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4613                                                 }
4614                                         }
4615                                         
4616                                         
4617                                         emitpLabel(lbl->key);
4618                                         
4619                                         rFalseIfx.condition ^= 1;
4620                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4621                                 }
4622                                 
4623                                 if(sign)
4624                                         emitpLabel(truelbl->key);
4625                                 if(ifx) ifx->generated = 1;
4626                                 return;
4627                         }
4628                 }
4629                 /* Compare two variables */
4630                 
4631                 DEBUGpic14_emitcode(";sign","%d",sign);
4632                 
4633                 size--;
4634                 if(sign) {
4635                         /* Sigh. thus sucks... */
4636                         if(size) {
4637                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4638                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4639                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4640                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4641                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4642                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4643                         } else {
4644                                 /* Signed char comparison */
4645                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4646                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4647                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4648                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4649                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4650                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4651                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4652                                 
4653                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4654                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4655                                 
4656                                 if(ifx) ifx->generated = 1;
4657                                 return;
4658                         }
4659                         
4660                 } else {
4661                         
4662                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4663                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4664                 }
4665                 
4666                 
4667                 /* The rest of the bytes of a multi-byte compare */
4668                 while (size) {
4669                         
4670                         emitSKPZ;
4671                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4672                         size--;
4673                         
4674                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4675                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4676                         
4677                         
4678                 }
4679                 
4680                 emitpLabel(lbl->key);
4681                 
4682                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4683                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4684                         (AOP_TYPE(result) == AOP_REG)) {
4685                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4686                         emitpcode(POC_RLF, popGet(AOP(result),0));
4687                 } else {
4688                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4689                 }       
4690                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4691                 if(ifx) ifx->generated = 1;
4692                 
4693                 return;
4694                 
4695         }
4696         
4697         // check_carry:
4698         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4699                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4700                 pic14_outBitC(result);
4701         } else {
4702                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4703                 /* if the result is used in the next
4704                 ifx conditional branch then generate
4705                 code a little differently */
4706                 if (ifx )
4707                         genIfxJump (ifx,"c");
4708                 else
4709                         pic14_outBitC(result);
4710                 /* leave the result in acc */
4711         }
4712         
4713 }
4714 #endif
4715
4716 /*-----------------------------------------------------------------*/
4717 /* genCmpGt :- greater than comparison                             */
4718 /*-----------------------------------------------------------------*/
4719 static void genCmpGt (iCode *ic, iCode *ifx)
4720 {
4721         operand *left, *right, *result;
4722         sym_link *letype , *retype;
4723         int sign ;
4724         
4725         FENTRY;
4726         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4727         left = IC_LEFT(ic);
4728         right= IC_RIGHT(ic);
4729         result = IC_RESULT(ic);
4730         
4731         letype = getSpec(operandType(left));
4732         retype =getSpec(operandType(right));
4733         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4734         /* assign the amsops */
4735         aopOp (left,ic,FALSE);
4736         aopOp (right,ic,FALSE);
4737         aopOp (result,ic,TRUE);
4738         
4739         genCmp(right, left, result, ifx, sign);
4740         
4741         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4742         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4743         freeAsmop(result,NULL,ic,TRUE); 
4744 }
4745
4746 /*-----------------------------------------------------------------*/
4747 /* genCmpLt - less than comparisons                                */
4748 /*-----------------------------------------------------------------*/
4749 static void genCmpLt (iCode *ic, iCode *ifx)
4750 {
4751         operand *left, *right, *result;
4752         sym_link *letype , *retype;
4753         int sign ;
4754         
4755         FENTRY;
4756         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4757         left = IC_LEFT(ic);
4758         right= IC_RIGHT(ic);
4759         result = IC_RESULT(ic);
4760         
4761         letype = getSpec(operandType(left));
4762         retype =getSpec(operandType(right));
4763         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4764         
4765         /* assign the amsops */
4766         aopOp (left,ic,FALSE);
4767         aopOp (right,ic,FALSE);
4768         aopOp (result,ic,TRUE);
4769         
4770         genCmp(left, right, result, ifx, sign);
4771         
4772         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4773         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4774         freeAsmop(result,NULL,ic,TRUE); 
4775 }
4776
4777 /*-----------------------------------------------------------------*/
4778 /* genc16bit2lit - compare a 16 bit value to a literal             */
4779 /*-----------------------------------------------------------------*/
4780 static void genc16bit2lit(operand *op, int lit, int offset)
4781 {
4782         int i;
4783         
4784         FENTRY;
4785         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4786         if( (lit&0xff) == 0) 
4787                 i=1;
4788         else
4789                 i=0;
4790         
4791         switch( BYTEofLONG(lit,i)) { 
4792         case 0:
4793                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4794                 break;
4795         case 1:
4796                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4797                 break;
4798         case 0xff:
4799                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4800                 break;
4801         default:
4802                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4803                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4804         }
4805         
4806         i ^= 1;
4807         
4808         switch( BYTEofLONG(lit,i)) { 
4809         case 0:
4810                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4811                 break;
4812         case 1:
4813                 emitSKPNZ;
4814                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4815                 break;
4816         case 0xff:
4817                 emitSKPNZ;
4818                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4819                 break;
4820         default:
4821                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4822                 emitSKPNZ;
4823                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4824                 
4825         }
4826         
4827 }
4828
4829 /*-----------------------------------------------------------------*/
4830 /* gencjneshort - compare and jump if not equal                    */
4831 /*-----------------------------------------------------------------*/
4832 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4833 {
4834         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4835         int offset = 0;
4836         //resolvedIfx rIfx;
4837         symbol *lbl;
4838         
4839         //unsigned long lit = 0L;
4840         FENTRY;
4841         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4842           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4843           return;
4844         }
4845         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4846         DEBUGpic14_AopType(__LINE__,left,right,result);
4847         
4848         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4849         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4850         if (AOP_SIZE(result)) {
4851           for (offset = 0; offset < AOP_SIZE(result); offset++)
4852             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4853         }
4854         
4855         assert (AOP_SIZE(left) == AOP_SIZE(right));
4856         //resolveIfx(&rIfx,ifx);
4857         lbl = newiTempLabel (NULL);
4858         while (size--)
4859         {
4860           mov2w (AOP(right),size);
4861           emitpcode (POC_XORFW, popGet (AOP(left), size));
4862           if (size)
4863           {
4864             emitSKPZ;
4865             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4866           }
4867         } // while
4868         emitpLabel (lbl->key);
4869         if (AOP_SIZE(result)) {
4870           emitSKPNZ;
4871           emitpcode (POC_INCF, popGet (AOP(result), 0));
4872         } else {
4873           assert (ifx);
4874           genSkipz (ifx, NULL != IC_TRUE(ifx));
4875           ifx->generated = 1;
4876         }
4877         return;
4878 #if 0   
4879         if(result)
4880         {
4881                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4882                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4883                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4884                 for (offset=0; offset < AOP_SIZE(result); offset++)
4885                 {
4886                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4887                 } // for offset
4888         }
4889         
4890         
4891         /* if the left side is a literal or 
4892         if the right is in a pointer register and left 
4893         is not */
4894         if ((AOP_TYPE(left) == AOP_LIT) || 
4895                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4896                 operand *t = right;
4897                 right = left;
4898                 left = t;
4899         }
4900         if(AOP_TYPE(right) == AOP_LIT)
4901                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4902         
4903         /* if the right side is a literal then anything goes */
4904         if (AOP_TYPE(right) == AOP_LIT &&
4905                 AOP_TYPE(left) != AOP_DIR ) {
4906                 switch(size) {
4907                 case 2:
4908                         genc16bit2lit(left, lit, 0);
4909                         emitSKPNZ;
4910                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4911                         break;
4912                 default:
4913                         offset = 0;
4914                         while (size--) {
4915                                 if(lit & 0xff) {
4916                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4917                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4918                                 } else {
4919                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4920                                 }
4921                                 
4922                                 emitSKPNZ;
4923                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4924                                 offset++;
4925                                 lit >>= 8;
4926                         }
4927                         break;
4928                 }
4929         }
4930         
4931         /* if the right side is in a register or in direct space or
4932         if the left is a pointer register & right is not */    
4933         else if (AOP_TYPE(right) == AOP_REG ||
4934                 AOP_TYPE(right) == AOP_DIR || 
4935                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4936                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4937                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4938                 int lbl_key = lbl->key;
4939                 
4940                 if(!result) {
4941                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4942                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4943                                 __FUNCTION__,__LINE__);
4944                         return;
4945                 }
4946                 
4947                 /*     switch(size) { */
4948                 /*     case 2: */
4949                 /*       genc16bit2lit(left, lit, 0); */
4950                 /*       emitSKPNZ; */
4951                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4952                 /*       break; */
4953                 /*     default: */
4954                 offset = 0;
4955                 while (size--) {
4956                         int emit_skip=1;
4957                         if((AOP_TYPE(left) == AOP_DIR) && 
4958                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4959                                 
4960                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4961                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4962                                 
4963                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4964                                 
4965                                 switch (lit & 0xff) {
4966                                 case 0:
4967                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4968                                         break;
4969                                 case 1:
4970                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4971                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4972                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4973                                         emit_skip=0;
4974                                         break;
4975                                 case 0xff:
4976                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4977                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4978                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4979                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4980                                         emit_skip=0;
4981                                         break;
4982                                 default:
4983                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4984                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4985                                 }
4986                                 lit >>= 8;
4987                                 
4988                         } else {
4989                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4990                         }
4991                         if(emit_skip) {
4992                                 if(AOP_TYPE(result) == AOP_CRY) {
4993                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4994                                         if(rIfx.condition)
4995                                                 emitSKPNZ;
4996                                         else
4997                                                 emitSKPZ;
4998                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4999                                 } else {
5000                                         /* fix me. probably need to check result size too */
5001                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5002                                         if(rIfx.condition)
5003                                                 emitSKPZ;
5004                                         else
5005                                                 emitSKPNZ;
5006                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5007                                 }
5008                                 if(ifx)
5009                                         ifx->generated=1;
5010                         }
5011                         emit_skip++;
5012                         offset++;
5013                 }
5014                 /*       break; */
5015                 /*     } */
5016         } else if(AOP_TYPE(right) == AOP_REG &&
5017                 AOP_TYPE(left) != AOP_DIR){
5018
5019                 offset = 0;
5020                 while(size--) {
5021                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5022                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5023                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5024                         if(rIfx.condition)
5025                                 emitSKPNZ;
5026                         else
5027                                 emitSKPZ;
5028                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5029                         offset++;
5030                 }
5031                 
5032         }else{
5033                 /* right is a pointer reg need both a & b */
5034                 offset = 0;
5035                 while(size--) {
5036                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5037                         if(strcmp(l,"b"))
5038                                 pic14_emitcode("mov","b,%s",l);
5039                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5040                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5041                         offset++;
5042                 }
5043         }
5044         
5045         emitpcode(POC_INCF,popGet(AOP(result),0));
5046         if(!rIfx.condition)
5047                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5048         
5049         emitpLabel(lbl->key);
5050         
5051         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5052         
5053         if(ifx)
5054                 ifx->generated = 1;
5055 #endif
5056 }
5057
5058 #if 0
5059 /*-----------------------------------------------------------------*/
5060 /* gencjne - compare and jump if not equal                         */
5061 /*-----------------------------------------------------------------*/
5062 static void gencjne(operand *left, operand *right, iCode *ifx)
5063 {
5064         symbol *tlbl  = newiTempLabel(NULL);
5065         
5066         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5067         gencjneshort(left, right, lbl);
5068         
5069         pic14_emitcode("mov","a,%s",one);
5070         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5071         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5072         pic14_emitcode("clr","a");
5073         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5074         
5075         emitpLabel(lbl->key);
5076         emitpLabel(tlbl->key);
5077         
5078 }
5079 #endif
5080
5081 /*-----------------------------------------------------------------*/
5082 /* genCmpEq - generates code for equal to                          */
5083 /*-----------------------------------------------------------------*/
5084 static void genCmpEq (iCode *ic, iCode *ifx)
5085 {
5086         operand *left, *right, *result;
5087         unsigned long lit = 0L;
5088         int size,offset=0;
5089         
5090         FENTRY;
5091         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5092         
5093         if(ifx)
5094                 DEBUGpic14_emitcode ("; ifx is non-null","");
5095         else
5096                 DEBUGpic14_emitcode ("; ifx is null","");
5097         
5098         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5099         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5100         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5101         
5102         size = max(AOP_SIZE(left),AOP_SIZE(right));
5103         
5104         DEBUGpic14_AopType(__LINE__,left,right,result);
5105         
5106         /* if literal, literal on the right or 
5107         if the right is in a pointer register and left 
5108         is not */
5109         if (aop_isLitLike (AOP(IC_LEFT(ic)))
5110                         || (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5111                 operand *tmp = right ;
5112                 right = left;
5113                 left = tmp;
5114         }
5115         
5116         
5117         if(ifx && !AOP_SIZE(result)){
5118                 symbol *tlbl;
5119                 /* if they are both bit variables */
5120                 if (AOP_TYPE(left) == AOP_CRY &&
5121                         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5122                         if(AOP_TYPE(right) == AOP_LIT){
5123                                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5124                                 if(lit == 0L){
5125                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5126                                         pic14_emitcode("cpl","c");
5127                                 } else if(lit == 1L) {
5128                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5129                                 } else {
5130                                         pic14_emitcode("clr","c");
5131                                 }
5132                                 /* AOP_TYPE(right) == AOP_CRY */
5133                         } else {
5134                                 symbol *lbl = newiTempLabel(NULL);
5135                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5136                                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5137                                 pic14_emitcode("cpl","c");
5138                                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5139                         }
5140                         /* if true label then we jump if condition
5141                         supplied is true */
5142                         tlbl = newiTempLabel(NULL);
5143                         if ( IC_TRUE(ifx) ) {
5144                                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
5145                                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5146                         } else {
5147                                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
5148                                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5149                         }
5150                         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5151                         
5152                         {
5153                                 /* left and right are both bit variables, result is carry */
5154                                 resolvedIfx rIfx;
5155                                 
5156                                 resolveIfx(&rIfx,ifx);
5157                                 
5158                                 emitpcode(POC_MOVLW,popGet(AOP(left),0));
5159                                 emitpcode(POC_ANDFW,popGet(AOP(left),0));
5160                                 emitpcode(POC_BTFSC,popGet(AOP(right),0));
5161                                 emitpcode(POC_ANDLW,popGet(AOP(left),0));
5162                                 genSkipz2(&rIfx,0);
5163                         }
5164                 } else {
5165                         
5166                         /* They're not both bit variables. Is the right a literal? */
5167                         if(AOP_TYPE(right) == AOP_LIT) {
5168                                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5169                                 
5170                                 switch(size) {
5171                                         
5172                                 case 1:
5173                                         switch(lit & 0xff) {
5174                                         case 1:
5175                                                 if ( IC_TRUE(ifx) ) {
5176                                                         emitpcode(POC_DECFW,popGet(AOP(left),offset));
5177                                                         emitSKPNZ;
5178                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5179                                                 } else {
5180                                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5181                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5182                                                 }
5183                                                 break;
5184                                         case 0xff:
5185                                                 if ( IC_TRUE(ifx) ) {
5186                                                         emitpcode(POC_INCFW,popGet(AOP(left),offset));
5187                                                         emitSKPNZ;
5188                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5189                                                 } else {
5190                                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5191                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5192                                                 }
5193                                                 break;
5194                                         default:
5195                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5196                                                 if(lit)
5197                                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5198                                                 genSkip(ifx,'z');
5199                                         }
5200                                         
5201                                         
5202                                         /* end of size == 1 */
5203                                         break;
5204                                         
5205                                         case 2:
5206                                                 genc16bit2lit(left,lit,offset);
5207                                                 genSkip(ifx,'z');
5208                                                 break;
5209                                                 /* end of size == 2 */
5210                                                 
5211                                         default:
5212                                                 /* size is 4 */
5213                                                 if(lit==0) {
5214                                                         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5215                                                         emitpcode(POC_IORFW,popGet(AOP(left),1));
5216                                                         emitpcode(POC_IORFW,popGet(AOP(left),2));
5217                                                         emitpcode(POC_IORFW,popGet(AOP(left),3));
5218                                                         
5219                                                 } else {
5220                                                         
5221                                                         /* search for patterns that can be optimized */
5222                                                         
5223                                                         genc16bit2lit(left,lit,0);
5224                                                         lit >>= 16;
5225                                                         if(lit) {
5226                                                                 genSkipz(ifx,IC_TRUE(ifx) == NULL);
5227                                                                 //genSkip(ifx,'z');
5228                                                                 genc16bit2lit(left,lit,2);
5229                                                         } else {
5230                                                                 emitpcode(POC_IORFW,popGet(AOP(left),2));
5231                                                                 emitpcode(POC_IORFW,popGet(AOP(left),3));
5232                                                                 
5233                                                         }
5234                                                         
5235                                                 }
5236                                                 
5237                                                 genSkip(ifx,'z');
5238                                 }
5239                                 
5240                                 ifx->generated = 1;
5241                                 goto release ;
5242                                 
5243                                 
5244                         } else if(AOP_TYPE(right) == AOP_CRY ) {
5245                                 /* we know the left is not a bit, but that the right is */
5246                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5247                                 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5248                                         popGet(AOP(right),offset));
5249                                 emitpcode(POC_XORLW,popGetLit(1));
5250                                 
5251                                 /* if the two are equal, then W will be 0 and the Z bit is set
5252                                 * we could test Z now, or go ahead and check the high order bytes if
5253                                 * the variable we're comparing is larger than a byte. */
5254                                 
5255                                 while(--size)
5256                                         emitpcode(POC_IORFW,popGet(AOP(left),offset));
5257                                 
5258                                 if ( IC_TRUE(ifx) ) {
5259                                         emitSKPNZ;
5260                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5261                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5262                                 } else {
5263                                         emitSKPZ;
5264                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5265                                         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5266                                 }
5267                                 
5268                         } else {
5269                                 /* They're both variables that are larger than bits */
5270                                 int s = size;
5271                                 
5272                                 tlbl = newiTempLabel(NULL);
5273                                 
5274                                 while(size--) {
5275                                         mov2w (AOP(right),offset); /* right might be litLike() */
5276                                         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5277                                         
5278                                         if ( IC_TRUE(ifx) ) {
5279                                                 if(size) {
5280                                                         emitSKPZ;
5281                                                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5282                                                         pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5283                                                 } else {
5284                                                         emitSKPNZ;
5285                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5286                                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5287                                                 }
5288                                         } else {
5289                                                 emitSKPZ;
5290                                                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5291                                                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5292                                         }
5293                                         offset++;
5294                                 }
5295                                 if(s>1 && IC_TRUE(ifx)) {
5296                                         emitpLabel(tlbl->key);
5297                                         pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5298                                 }
5299                         }
5300                 }
5301                 /* mark the icode as generated */
5302                 ifx->generated = 1;
5303                 goto release ;
5304         }
5305   
5306   /* if they are both bit variables */
5307   if (AOP_TYPE(left) == AOP_CRY &&
5308           ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5309           if(AOP_TYPE(right) == AOP_LIT){
5310                   unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5311                   if(lit == 0L){
5312                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5313                           pic14_emitcode("cpl","c");
5314                   } else if(lit == 1L) {
5315                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5316                   } else {
5317                           pic14_emitcode("clr","c");
5318                   }
5319                   /* AOP_TYPE(right) == AOP_CRY */
5320           } else {
5321                   symbol *lbl = newiTempLabel(NULL);
5322                   pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5323                   pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5324                   pic14_emitcode("cpl","c");
5325                   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5326           }
5327           /* c = 1 if egal */
5328           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5329                   pic14_outBitC(result);
5330                   goto release ;
5331           }
5332           if (ifx) {
5333                   genIfxJump (ifx,"c");
5334                   goto release ;
5335           }
5336           /* if the result is used in an arithmetic operation
5337           then put the result in place */
5338           pic14_outBitC(result);
5339   } else {
5340           
5341           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5342           gencjne(left,right,result,ifx);
5343           /*
5344           if(ifx) 
5345           gencjne(left,right,newiTempLabel(NULL));
5346           else {
5347           if(IC_TRUE(ifx)->key)
5348           gencjne(left,right,IC_TRUE(ifx)->key);
5349           else
5350           gencjne(left,right,IC_FALSE(ifx)->key);
5351           ifx->generated = 1;
5352           goto release ;
5353           }
5354           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5355           aopPut(AOP(result),"a",0);
5356           goto release ;
5357           }
5358           
5359                 if (ifx) {
5360                 genIfxJump (ifx,"a");
5361                 goto release ;
5362                 }
5363           */
5364           /* if the result is used in an arithmetic operation
5365           then put the result in place */
5366           /*
5367           if (AOP_TYPE(result) != AOP_CRY) 
5368           pic14_outAcc(result);
5369           */
5370           /* leave the result in acc */
5371   }
5372   
5373 release:
5374   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5375   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5376   freeAsmop(result,NULL,ic,TRUE);
5377 }
5378
5379 /*-----------------------------------------------------------------*/
5380 /* ifxForOp - returns the icode containing the ifx for operand     */
5381 /*-----------------------------------------------------------------*/
5382 static iCode *ifxForOp ( operand *op, iCode *ic )
5383 {
5384         FENTRY;
5385         /* if true symbol then needs to be assigned */
5386         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5387         if (IS_TRUE_SYMOP(op))
5388                 return NULL ;
5389         
5390         /* if this has register type condition and
5391         the next instruction is ifx with the same operand
5392         and live to of the operand is upto the ifx only then */
5393         if (ic->next &&
5394                 ic->next->op == IFX &&
5395                 IC_COND(ic->next)->key == op->key &&
5396                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5397                 return ic->next;
5398         
5399         if (ic->next &&
5400                 ic->next->op == IFX &&
5401                 IC_COND(ic->next)->key == op->key) {
5402                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5403                 return ic->next;
5404         }
5405         
5406         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5407         if (ic->next &&
5408                 ic->next->op == IFX)
5409                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5410         
5411         if (ic->next &&
5412                 ic->next->op == IFX &&
5413                 IC_COND(ic->next)->key == op->key) {
5414                 DEBUGpic14_emitcode ("; "," key is okay");
5415                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5416                         OP_SYMBOL(op)->liveTo,
5417                         ic->next->seq);
5418         }
5419         
5420         
5421         return NULL;
5422 }
5423 /*-----------------------------------------------------------------*/
5424 /* genAndOp - for && operation                                     */
5425 /*-----------------------------------------------------------------*/
5426 static void genAndOp (iCode *ic)
5427 {
5428         operand *left,*right, *result;
5429         /*     symbol *tlbl; */
5430         
5431         FENTRY;
5432         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5433         /* note here that && operations that are in an
5434         if statement are taken away by backPatchLabels
5435         only those used in arthmetic operations remain */
5436         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5437         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5438         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5439         
5440         DEBUGpic14_AopType(__LINE__,left,right,result);
5441         
5442         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5443         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5444         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5445         
5446         /* if both are bit variables */
5447         /*     if (AOP_TYPE(left) == AOP_CRY && */
5448         /*         AOP_TYPE(right) == AOP_CRY ) { */
5449         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5450         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5451         /*         pic14_outBitC(result); */
5452         /*     } else { */
5453         /*         tlbl = newiTempLabel(NULL); */
5454         /*         pic14_toBoolean(left);     */
5455         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5456         /*         pic14_toBoolean(right); */
5457         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5458         /*         pic14_outBitAcc(result); */
5459         /*     } */
5460         
5461         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5462         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5463         freeAsmop(result,NULL,ic,TRUE);
5464 }
5465
5466
5467 /*-----------------------------------------------------------------*/
5468 /* genOrOp - for || operation                                      */
5469 /*-----------------------------------------------------------------*/
5470 /*
5471 tsd pic port -
5472 modified this code, but it doesn't appear to ever get called
5473 */
5474
5475 static void genOrOp (iCode *ic)
5476 {
5477         operand *left,*right, *result;
5478         symbol *tlbl;
5479         
5480         /* note here that || operations that are in an
5481         if statement are taken away by backPatchLabels
5482         only those used in arthmetic operations remain */
5483         FENTRY;
5484         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5485         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5486         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5487         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5488         
5489         DEBUGpic14_AopType(__LINE__,left,right,result);
5490         
5491         /* if both are bit variables */
5492         if (AOP_TYPE(left) == AOP_CRY &&
5493                 AOP_TYPE(right) == AOP_CRY ) {
5494                 pic14_emitcode("clrc","");
5495                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5496                         AOP(left)->aopu.aop_dir,
5497                         AOP(left)->aopu.aop_dir);
5498                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5499                         AOP(right)->aopu.aop_dir,
5500                         AOP(right)->aopu.aop_dir);
5501                 pic14_emitcode("setc","");
5502                 
5503         } else {
5504                 tlbl = newiTempLabel(NULL);
5505                 pic14_toBoolean(left);
5506                 emitSKPZ;
5507                 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5508                 pic14_toBoolean(right);
5509                 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5510                 
5511                 pic14_outBitAcc(result);
5512         }
5513         
5514         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5515         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5516         freeAsmop(result,NULL,ic,TRUE);            
5517 }
5518
5519 /*-----------------------------------------------------------------*/
5520 /* isLiteralBit - test if lit == 2^n                               */
5521 /*-----------------------------------------------------------------*/
5522 static int isLiteralBit(unsigned long lit)
5523 {
5524         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5525                 0x100L,0x200L,0x400L,0x800L,
5526                 0x1000L,0x2000L,0x4000L,0x8000L,
5527                 0x10000L,0x20000L,0x40000L,0x80000L,
5528                 0x100000L,0x200000L,0x400000L,0x800000L,
5529                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5530                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5531         int idx;
5532         
5533         FENTRY;
5534         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5535         for(idx = 0; idx < 32; idx++)
5536                 if(lit == pw[idx])
5537                         return idx+1;
5538                 return 0;
5539 }
5540
5541 /*-----------------------------------------------------------------*/
5542 /* continueIfTrue -                                                */
5543 /*-----------------------------------------------------------------*/
5544 static void continueIfTrue (iCode *ic)
5545 {
5546         FENTRY;
5547         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5548         if(IC_TRUE(ic))
5549                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5550         ic->generated = 1;
5551 }
5552
5553 /*-----------------------------------------------------------------*/
5554 /* jmpIfTrue -                                                     */
5555 /*-----------------------------------------------------------------*/
5556 static void jumpIfTrue (iCode *ic)
5557 {
5558         FENTRY;
5559         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5560         if(!IC_TRUE(ic))
5561                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5562         ic->generated = 1;
5563 }
5564
5565 /*-----------------------------------------------------------------*/
5566 /* jmpTrueOrFalse -                                                */
5567 /*-----------------------------------------------------------------*/
5568 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5569 {
5570         FENTRY;
5571         // ugly but optimized by peephole
5572         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5573         if(IC_TRUE(ic)){
5574                 symbol *nlbl = newiTempLabel(NULL);
5575                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5576                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5577                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5578                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5579         }
5580         else{
5581                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5582                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5583         }
5584         ic->generated = 1;
5585 }
5586
5587 /*-----------------------------------------------------------------*/
5588 /* genAnd  - code for and                                          */
5589 /*-----------------------------------------------------------------*/
5590 static void genAnd (iCode *ic, iCode *ifx)
5591 {
5592         operand *left, *right, *result;
5593         int size, offset=0;  
5594         unsigned long lit = 0L;
5595         int bytelit = 0;
5596         resolvedIfx rIfx;
5597         
5598         FENTRY;
5599         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5600         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5601         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5602         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5603         
5604         resolveIfx(&rIfx,ifx);
5605         
5606         /* if left is a literal & right is not then exchange them */
5607         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5608                 AOP_NEEDSACC(left)) {
5609                 operand *tmp = right ;
5610                 right = left;
5611                 left = tmp;
5612         }
5613         
5614         /* if result = right then exchange them */
5615         if(pic14_sameRegs(AOP(result),AOP(right))){
5616                 operand *tmp = right ;
5617                 right = left;
5618                 left = tmp;
5619         }
5620         
5621         /* if right is bit then exchange them */
5622         if (AOP_TYPE(right) == AOP_CRY &&
5623                 AOP_TYPE(left) != AOP_CRY){
5624                 operand *tmp = right ;
5625                 right = left;
5626                 left = tmp;
5627         }
5628         if(AOP_TYPE(right) == AOP_LIT)
5629                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5630         
5631         size = AOP_SIZE(result);
5632         
5633         DEBUGpic14_AopType(__LINE__,left,right,result);
5634         
5635         // if(bit & yy)
5636         // result = bit & yy;
5637         if (AOP_TYPE(left) == AOP_CRY){
5638                 // c = bit & literal;
5639                 if(AOP_TYPE(right) == AOP_LIT){
5640                         if(lit & 1) {
5641                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5642                                         // no change
5643                                         goto release;
5644                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5645                         } else {
5646                                 // bit(result) = 0;
5647                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5648                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5649                                         goto release;
5650                                 }
5651                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5652                                         jumpIfTrue(ifx);
5653                                         goto release;
5654                                 }
5655                                 pic14_emitcode("clr","c");
5656                         }
5657                 } else {
5658                         if (AOP_TYPE(right) == AOP_CRY){
5659                                 // c = bit & bit;
5660                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5661                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5662                         } else {
5663                                 // c = bit & val;
5664                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5665                                 // c = lsb
5666                                 pic14_emitcode("rrc","a");
5667                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5668                         }
5669                 }
5670                 // bit = c
5671                 // val = c
5672                 if(size)
5673                         pic14_outBitC(result);
5674                 // if(bit & ...)
5675                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5676                         genIfxJump(ifx, "c");           
5677                 goto release ;
5678         }
5679         
5680         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5681         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5682         if((AOP_TYPE(right) == AOP_LIT) &&
5683                 (AOP_TYPE(result) == AOP_CRY) &&
5684                 (AOP_TYPE(left) != AOP_CRY)){
5685                 int posbit = isLiteralBit(lit);
5686                 /* left &  2^n */
5687                 if(posbit){
5688                         posbit--;
5689                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5690                         // bit = left & 2^n
5691                         if(size)
5692                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5693                         // if(left &  2^n)
5694                         else{
5695                                 if(ifx){
5696                                         int offset = 0;
5697                                         while (posbit > 7) {
5698                                                 posbit -= 8;
5699                                                 offset++;
5700                                         }
5701                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5702                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5703                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5704                                         
5705                                         ifx->generated = 1;
5706                                 }
5707                                 goto release;
5708                         }
5709                 } else {
5710                         symbol *tlbl = newiTempLabel(NULL);
5711                         int sizel = AOP_SIZE(left);
5712                         if(size)
5713                                 pic14_emitcode("setb","c");
5714                         while(sizel--){
5715                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5716                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5717                                         // byte ==  2^n ?
5718                                         if((posbit = isLiteralBit(bytelit)) != 0)
5719                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5720                                         else{
5721                                                 if(bytelit != 0x0FFL)
5722                                                         pic14_emitcode("anl","a,%s",
5723                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5724                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5725                                         }
5726                                 }
5727                                 offset++;
5728                         }
5729                         // bit = left & literal
5730                         if(size){
5731                                 pic14_emitcode("clr","c");
5732                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5733                         }
5734                         // if(left & literal)
5735                         else{
5736                                 if(ifx)
5737                                         jmpTrueOrFalse(ifx, tlbl);
5738                                 goto release ;
5739                         }
5740                 }
5741                 pic14_outBitC(result);
5742                 goto release ;
5743         }
5744         
5745         /* if left is same as result */
5746         if(pic14_sameRegs(AOP(result),AOP(left))){
5747                 int know_W = -1;
5748                 for(;size--; offset++,lit>>=8) {
5749                         if(AOP_TYPE(right) == AOP_LIT){
5750                                 switch(lit & 0xff) {
5751                                 case 0x00:
5752                                         /*  and'ing with 0 has clears the result */
5753                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5754                                         break;
5755                                 case 0xff:
5756                                         /* and'ing with 0xff is a nop when the result and left are the same */
5757                                         break;
5758                                         
5759                                 default:
5760                                         {
5761                                                 int p = my_powof2( (~lit) & 0xff );
5762                                                 if(p>=0) {
5763                                                         /* only one bit is set in the literal, so use a bcf instruction */
5764                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5765                                                         
5766                                                 } else {
5767                                                         if(know_W != (int)(lit&0xff))
5768                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5769                                                         know_W = lit &0xff;
5770                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5771                                                 }
5772                                         }    
5773                                 }
5774                         } else {
5775                                 if (AOP_TYPE(left) == AOP_ACC) {
5776                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5777                                 } else {        
5778                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5779                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5780                                         
5781                                 }
5782                         }
5783                 }
5784                 
5785         } else {
5786                 // left & result in different registers
5787                 if(AOP_TYPE(result) == AOP_CRY){
5788                         // result = bit
5789                         // if(size), result in bit
5790                         // if(!size && ifx), conditional oper: if(left & right)
5791                         symbol *tlbl = newiTempLabel(NULL);
5792                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5793                         if(size)
5794                                 pic14_emitcode("setb","c");
5795                         while(sizer--){
5796                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5797                                 pic14_emitcode("anl","a,%s",
5798                                         aopGet(AOP(left),offset,FALSE,FALSE));
5799                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5800                                 offset++;
5801                         }
5802                         if(size){
5803                                 CLRC;
5804                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5805                                 pic14_outBitC(result);
5806                         } else if(ifx)
5807                                 jmpTrueOrFalse(ifx, tlbl);
5808                 } else {
5809                         for(;(size--);offset++) {
5810                                 // normal case
5811                                 // result = left & right
5812                                 if(AOP_TYPE(right) == AOP_LIT){
5813                                         int t = (lit >> (offset*8)) & 0x0FFL;
5814                                         switch(t) { 
5815                                         case 0x00:
5816                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5817                                                 break;
5818                                         case 0xff:
5819                                                 if(AOP_TYPE(left) != AOP_ACC) {
5820                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5821                                                 }
5822                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5823                                                 break;
5824                                         default:
5825                                                 if(AOP_TYPE(left) == AOP_ACC) {
5826                                                         emitpcode(POC_ANDLW, popGetLit(t));
5827                                                 } else {
5828                                                         emitpcode(POC_MOVLW, popGetLit(t));
5829                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5830                                                 }
5831                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5832                                         }
5833                                         continue;
5834                                 }
5835                                 
5836                                 if (AOP_TYPE(left) == AOP_ACC) {
5837                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5838                                 } else {
5839                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5840                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5841                                 }
5842                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5843                         }
5844                 }
5845         }
5846         
5847 release :
5848         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5849         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5850         freeAsmop(result,NULL,ic,TRUE);     
5851 }
5852
5853 /*-----------------------------------------------------------------*/
5854 /* genOr  - code for or                                            */
5855 /*-----------------------------------------------------------------*/
5856 static void genOr (iCode *ic, iCode *ifx)
5857 {
5858         operand *left, *right, *result;
5859         int size, offset=0;
5860         unsigned long lit = 0L;
5861         
5862         FENTRY;
5863         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5864         
5865         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5866         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5867         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5868         
5869         DEBUGpic14_AopType(__LINE__,left,right,result);
5870         
5871         /* if left is a literal & right is not then exchange them */
5872         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5873                 AOP_NEEDSACC(left)) {
5874                 operand *tmp = right ;
5875                 right = left;
5876                 left = tmp;
5877         }
5878         
5879         /* if result = right then exchange them */
5880         if(pic14_sameRegs(AOP(result),AOP(right))){
5881                 operand *tmp = right ;
5882                 right = left;
5883                 left = tmp;
5884         }
5885         
5886         /* if right is bit then exchange them */
5887         if (AOP_TYPE(right) == AOP_CRY &&
5888                 AOP_TYPE(left) != AOP_CRY){
5889                 operand *tmp = right ;
5890                 right = left;
5891                 left = tmp;
5892         }
5893         
5894         DEBUGpic14_AopType(__LINE__,left,right,result);
5895         
5896         if(AOP_TYPE(right) == AOP_LIT)
5897                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5898         
5899         size = AOP_SIZE(result);
5900         
5901         // if(bit | yy)
5902         // xx = bit | yy;
5903         if (AOP_TYPE(left) == AOP_CRY){
5904                 if(AOP_TYPE(right) == AOP_LIT){
5905                         // c = bit & literal;
5906                         if(lit){
5907                                 // lit != 0 => result = 1
5908                                 if(AOP_TYPE(result) == AOP_CRY){
5909                                         if(size)
5910                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5911                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5912                                         //   AOP(result)->aopu.aop_dir,
5913                                         //   AOP(result)->aopu.aop_dir);
5914                                         else if(ifx)
5915                                                 continueIfTrue(ifx);
5916                                         goto release;
5917                                 }
5918                         } else {
5919                                 // lit == 0 => result = left
5920                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5921                                         goto release;
5922                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5923                         }
5924                 } else {
5925                         if (AOP_TYPE(right) == AOP_CRY){
5926                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5927                                         // c = bit | bit;
5928                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5929                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5930                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5931                                         
5932                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5933                                                 AOP(result)->aopu.aop_dir,
5934                                                 AOP(result)->aopu.aop_dir);
5935                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5936                                                 AOP(right)->aopu.aop_dir,
5937                                                 AOP(right)->aopu.aop_dir);
5938                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5939                                                 AOP(result)->aopu.aop_dir,
5940                                                 AOP(result)->aopu.aop_dir);
5941                                 } else {
5942                                         if( AOP_TYPE(result) == AOP_ACC) {
5943                                                 emitpcode(POC_MOVLW, popGetLit(0));
5944                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5945                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5946                                                 emitpcode(POC_MOVLW, popGetLit(1));
5947                                                 
5948                                         } else {
5949                                                 
5950                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5951                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5952                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5953                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5954                                                 
5955                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5956                                                         AOP(result)->aopu.aop_dir,
5957                                                         AOP(result)->aopu.aop_dir);
5958                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5959                                                         AOP(right)->aopu.aop_dir,
5960                                                         AOP(right)->aopu.aop_dir);
5961                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5962                                                         AOP(left)->aopu.aop_dir,
5963                                                         AOP(left)->aopu.aop_dir);
5964                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5965                                                         AOP(result)->aopu.aop_dir,
5966                                                         AOP(result)->aopu.aop_dir);
5967                                         }
5968                                 }
5969                         } else {
5970                                 // c = bit | val;
5971                                 symbol *tlbl = newiTempLabel(NULL);
5972                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5973                                 
5974                                 
5975                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5976                                 if( AOP_TYPE(right) == AOP_ACC) {
5977                                         emitpcode(POC_IORLW, popGetLit(0));
5978                                         emitSKPNZ;
5979                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5980                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5981                                 }
5982                                 
5983                                 
5984                                 
5985                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5986                                         pic14_emitcode(";XXX setb","c");
5987                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5988                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5989                                 pic14_toBoolean(right);
5990                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5991                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5992                                         jmpTrueOrFalse(ifx, tlbl);
5993                                         goto release;
5994                                 } else {
5995                                         CLRC;
5996                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5997                                 }
5998                         }
5999                 }
6000                 // bit = c
6001                 // val = c
6002                 if(size)
6003                         pic14_outBitC(result);
6004                 // if(bit | ...)
6005                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6006                         genIfxJump(ifx, "c");           
6007                 goto release ;
6008         }
6009
6010         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6011         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6012         if((AOP_TYPE(right) == AOP_LIT) &&
6013           (AOP_TYPE(result) == AOP_CRY) &&
6014           (AOP_TYPE(left) != AOP_CRY)){
6015                 if(lit){
6016                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6017                         // result = 1
6018                         if(size)
6019                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6020                         else 
6021                                 continueIfTrue(ifx);
6022                         goto release;
6023                 } else {
6024                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6025                         // lit = 0, result = boolean(left)
6026                         if(size)
6027                                 pic14_emitcode(";XXX setb","c");
6028                         pic14_toBoolean(right);
6029                         if(size){
6030                                 symbol *tlbl = newiTempLabel(NULL);
6031                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6032                                 CLRC;
6033                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6034                         } else {
6035                                 genIfxJump (ifx,"a");
6036                                 goto release;
6037                         }
6038                 }
6039                 pic14_outBitC(result);
6040                 goto release ;
6041         }
6042
6043         /* if left is same as result */
6044         if(pic14_sameRegs(AOP(result),AOP(left))){
6045                 int know_W = -1;
6046                 for(;size--; offset++,lit>>=8) {
6047                         if(AOP_TYPE(right) == AOP_LIT){
6048                                 if((lit & 0xff) == 0)
6049                                         /*  or'ing with 0 has no effect */
6050                                         continue;
6051                                 else {
6052                                         int p = my_powof2(lit & 0xff);
6053                                         if(p>=0) {
6054                                                 /* only one bit is set in the literal, so use a bsf instruction */
6055                                                 emitpcode(POC_BSF,
6056                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6057                                         } else {
6058                                                 if(know_W != (int)(lit & 0xff))
6059                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6060                                                 know_W = lit & 0xff;
6061                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6062                                         }
6063                                         
6064                                 }
6065                         } else {
6066                                 if (AOP_TYPE(left) == AOP_ACC) {
6067                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
6068                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6069                                 } else {        
6070                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
6071                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
6072                                         
6073                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6074                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6075                                         
6076                                 }
6077                         }
6078                 }
6079         } else {
6080                 // left & result in different registers
6081                 if(AOP_TYPE(result) == AOP_CRY){
6082                         // result = bit
6083                         // if(size), result in bit
6084                         // if(!size && ifx), conditional oper: if(left | right)
6085                         symbol *tlbl = newiTempLabel(NULL);
6086                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6087                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6088                         
6089                         
6090                         if(size)
6091                                 pic14_emitcode(";XXX setb","c");
6092                         while(sizer--){
6093                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6094                                 pic14_emitcode(";XXX orl","a,%s",
6095                                         aopGet(AOP(left),offset,FALSE,FALSE));
6096                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6097                                 offset++;
6098                         }
6099                         if(size){
6100                                 CLRC;
6101                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6102                                 pic14_outBitC(result);
6103                         } else if(ifx)
6104                                 jmpTrueOrFalse(ifx, tlbl);
6105                 } else for(;(size--);offset++){
6106                         // normal case
6107                         // result = left | right
6108                         if(AOP_TYPE(right) == AOP_LIT){
6109                                 int t = (lit >> (offset*8)) & 0x0FFL;
6110                                 switch(t) { 
6111                                 case 0x00:
6112                                         if (AOP_TYPE(left) != AOP_ACC) {
6113                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6114                                         }
6115                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6116                                         
6117                                         break;
6118                                 default:
6119                                         if (AOP_TYPE(left) == AOP_ACC) {
6120                                                 emitpcode(POC_IORLW,  popGetLit(t));
6121                                         } else {
6122                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6123                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6124                                         }
6125                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6126                                 }
6127                                 continue;
6128                         }
6129                         
6130                         // faster than result <- left, anl result,right
6131                         // and better if result is SFR
6132                         if (AOP_TYPE(left) == AOP_ACC) {
6133                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6134                         } else {
6135                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6136                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6137                         }
6138                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6139                 }
6140         }
6141
6142 release :
6143         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6144         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6145         freeAsmop(result,NULL,ic,TRUE);     
6146 }
6147
6148 /*-----------------------------------------------------------------*/
6149 /* genXor - code for xclusive or                                   */
6150 /*-----------------------------------------------------------------*/
6151 static void genXor (iCode *ic, iCode *ifx)
6152 {
6153         operand *left, *right, *result;
6154         int size, offset=0;
6155         unsigned long lit = 0L;
6156         
6157         FENTRY;
6158         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6159         
6160         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6161         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6162         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6163         
6164         /* if left is a literal & right is not ||
6165         if left needs acc & right does not */
6166         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6167                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6168                 operand *tmp = right ;
6169                 right = left;
6170                 left = tmp;
6171         }
6172         
6173         /* if result = right then exchange them */
6174         if(pic14_sameRegs(AOP(result),AOP(right))){
6175                 operand *tmp = right ;
6176                 right = left;
6177                 left = tmp;
6178         }
6179         
6180         /* if right is bit then exchange them */
6181         if (AOP_TYPE(right) == AOP_CRY &&
6182                 AOP_TYPE(left) != AOP_CRY){
6183                 operand *tmp = right ;
6184                 right = left;
6185                 left = tmp;
6186         }
6187         if(AOP_TYPE(right) == AOP_LIT)
6188                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6189         
6190         size = AOP_SIZE(result);
6191         
6192         // if(bit ^ yy)
6193         // xx = bit ^ yy;
6194         if (AOP_TYPE(left) == AOP_CRY){
6195                 if(AOP_TYPE(right) == AOP_LIT){
6196                         // c = bit & literal;
6197                         if(lit>>1){
6198                                 // lit>>1  != 0 => result = 1
6199                                 if(AOP_TYPE(result) == AOP_CRY){
6200                                         if(size)
6201                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6202                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6203                                         else if(ifx)
6204                                                 continueIfTrue(ifx);
6205                                         goto release;
6206                                 }
6207                                 pic14_emitcode("setb","c");
6208                         } else{
6209                                 // lit == (0 or 1)
6210                                 if(lit == 0){
6211                                         // lit == 0, result = left
6212                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6213                                                 goto release;
6214                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6215                                 } else{
6216                                         // lit == 1, result = not(left)
6217                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6218                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6219                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6220                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6221                                                 goto release;
6222                                         } else {
6223                                                 assert ( !"incomplete genXor" );
6224                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6225                                                 pic14_emitcode("cpl","c");
6226                                         }
6227                                 }
6228                         }
6229                         
6230                 } else {
6231                         // right != literal
6232                         symbol *tlbl = newiTempLabel(NULL);
6233                         if (AOP_TYPE(right) == AOP_CRY){
6234                                 // c = bit ^ bit;
6235                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6236                         }
6237                         else{
6238                                 int sizer = AOP_SIZE(right);
6239                                 // c = bit ^ val
6240                                 // if val>>1 != 0, result = 1
6241                                 pic14_emitcode("setb","c");
6242                                 while(sizer){
6243                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6244                                         if(sizer == 1)
6245                                                 // test the msb of the lsb
6246                                                 pic14_emitcode("anl","a,#0xfe");
6247                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6248                                         sizer--;
6249                                 }
6250                                 // val = (0,1)
6251                                 pic14_emitcode("rrc","a");
6252                         }
6253                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6254                         pic14_emitcode("cpl","c");
6255                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6256                 }
6257                 // bit = c
6258                 // val = c
6259                 if(size)
6260                         pic14_outBitC(result);
6261                 // if(bit | ...)
6262                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6263                         genIfxJump(ifx, "c");           
6264                 goto release ;
6265         }
6266         
6267         if(pic14_sameRegs(AOP(result),AOP(left))){
6268                 /* if left is same as result */
6269                 for(;size--; offset++) {
6270                         if(AOP_TYPE(right) == AOP_LIT){
6271                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6272                                 if(t == 0x00L)
6273                                         continue;
6274                                 else
6275                                         if (IS_AOP_PREG(left)) {
6276                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6277                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6278                                                 aopPut(AOP(result),"a",offset);
6279                                         } else {
6280                                                 emitpcode(POC_MOVLW, popGetLit(t));
6281                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6282                                                 pic14_emitcode("xrl","%s,%s",
6283                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6284                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6285                                         }
6286                         } else {
6287                                 if (AOP_TYPE(left) == AOP_ACC)
6288                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6289                                 else {
6290                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6291                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6292                                         /*
6293                                         if (IS_AOP_PREG(left)) {
6294                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6295                                         aopPut(AOP(result),"a",offset);
6296                                         } else
6297                                         pic14_emitcode("xrl","%s,a",
6298                                         aopGet(AOP(left),offset,FALSE,TRUE));
6299                                         */
6300                                 }
6301                         }
6302                 }
6303         } else {
6304                 // left & result in different registers
6305                 if(AOP_TYPE(result) == AOP_CRY){
6306                         // result = bit
6307                         // if(size), result in bit
6308                         // if(!size && ifx), conditional oper: if(left ^ right)
6309                         symbol *tlbl = newiTempLabel(NULL);
6310                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6311                         if(size)
6312                                 pic14_emitcode("setb","c");
6313                         while(sizer--){
6314                                 if((AOP_TYPE(right) == AOP_LIT) &&
6315                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6316                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6317                                 } else {
6318                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6319                                         pic14_emitcode("xrl","a,%s",
6320                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6321                                 }
6322                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6323                                 offset++;
6324                         }
6325                         if(size){
6326                                 CLRC;
6327                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6328                                 pic14_outBitC(result);
6329                         } else if(ifx)
6330                                 jmpTrueOrFalse(ifx, tlbl);
6331                 } else for(;(size--);offset++){
6332                         // normal case
6333                         // result = left & right
6334                         if(AOP_TYPE(right) == AOP_LIT){
6335                                 int t = (lit >> (offset*8)) & 0x0FFL;
6336                                 switch(t) { 
6337                                 case 0x00:
6338                                         if (AOP_TYPE(left) != AOP_ACC) {
6339                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6340                                         }
6341                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6342                                         pic14_emitcode("movf","%s,w",
6343                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6344                                         pic14_emitcode("movwf","%s",
6345                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6346                                         break;
6347                                 case 0xff:
6348                                         if (AOP_TYPE(left) == AOP_ACC) {
6349                                                 emitpcode(POC_XORLW, popGetLit(t));
6350                                         } else {
6351                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6352                                         }
6353                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6354                                         break;
6355                                 default:
6356                                         if (AOP_TYPE(left) == AOP_ACC) {
6357                                                 emitpcode(POC_XORLW, popGetLit(t));
6358                                         } else {
6359                                                 emitpcode(POC_MOVLW, popGetLit(t));
6360                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6361                                         }
6362                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6363                                         pic14_emitcode("movlw","0x%x",t);
6364                                         pic14_emitcode("xorwf","%s,w",
6365                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6366                                         pic14_emitcode("movwf","%s",
6367                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6368                                         
6369                                 }
6370                                 continue;
6371                         }
6372                         
6373                         // faster than result <- left, anl result,right
6374                         // and better if result is SFR
6375                         if (AOP_TYPE(left) == AOP_ACC) {
6376                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6377                         } else {
6378                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6379                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6380                         }
6381                         if ( AOP_TYPE(result) != AOP_ACC){
6382                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6383                         }
6384                 }
6385         }
6386         
6387 release :
6388         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6389         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6390         freeAsmop(result,NULL,ic,TRUE);     
6391 }
6392
6393 /*-----------------------------------------------------------------*/
6394 /* genInline - write the inline code out                           */
6395 /*-----------------------------------------------------------------*/
6396 static void genInline (iCode *ic)
6397 {
6398   char *buffer, *bp, *bp1;
6399
6400   FENTRY;
6401   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6402
6403   _G.inLine += (!options.asmpeep);
6404
6405   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6406   strcpy(buffer,IC_INLINE(ic));
6407
6408   /* emit each line as a code */
6409   while (*bp) {
6410     if (*bp == '\n') {
6411       *bp++ = '\0';
6412       
6413       if(*bp1)
6414         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6415       bp1 = bp;
6416     } else {
6417       if (*bp == ':') {
6418         bp++;
6419         *bp = '\0';
6420         bp++;
6421
6422         /* print label, use this special format with NULL directive
6423          * to denote that the argument should not be indented with tab */
6424         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6425
6426         bp1 = bp;
6427       } else
6428         bp++;
6429     }
6430   }
6431   if ((bp1 != bp) && *bp1)
6432     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6433
6434   Safe_free(buffer);
6435
6436   _G.inLine -= (!options.asmpeep);
6437 }
6438
6439 /*-----------------------------------------------------------------*/
6440 /* genRRC - rotate right with carry                                */
6441 /*-----------------------------------------------------------------*/
6442 static void genRRC (iCode *ic)
6443 {
6444         operand *left , *result ;
6445         int size, offset = 0, same;
6446         
6447         FENTRY;
6448         /* rotate right with carry */
6449         left = IC_LEFT(ic);
6450         result=IC_RESULT(ic);
6451         aopOp (left,ic,FALSE);
6452         aopOp (result,ic,FALSE);
6453         
6454         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6455         
6456         same = pic14_sameRegs(AOP(result),AOP(left));
6457         
6458         size = AOP_SIZE(result);    
6459         
6460         /* get the lsb and put it into the carry */
6461         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6462         
6463         offset = 0 ;
6464         
6465         while(size--) {
6466                 
6467                 if(same) {
6468                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6469                 } else {
6470                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6471                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6472                 }
6473                 
6474                 offset++;
6475         }
6476         
6477         freeAsmop(left,NULL,ic,TRUE);
6478         freeAsmop(result,NULL,ic,TRUE);
6479 }
6480
6481 /*-----------------------------------------------------------------*/
6482 /* genRLC - generate code for rotate left with carry               */
6483 /*-----------------------------------------------------------------*/
6484 static void genRLC (iCode *ic)
6485 {    
6486         operand *left , *result ;
6487         int size, offset = 0;
6488         int same;
6489         
6490         FENTRY;
6491         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6492         /* rotate right with carry */
6493         left = IC_LEFT(ic);
6494         result=IC_RESULT(ic);
6495         aopOp (left,ic,FALSE);
6496         aopOp (result,ic,FALSE);
6497         
6498         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6499         
6500         same = pic14_sameRegs(AOP(result),AOP(left));
6501         
6502         /* move it to the result */
6503         size = AOP_SIZE(result);    
6504         
6505         /* get the msb and put it into the carry */
6506         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6507         
6508         offset = 0 ;
6509         
6510         while(size--) {
6511                 
6512                 if(same) {
6513                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6514                 } else {
6515                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6516                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6517                 }
6518                 
6519                 offset++;
6520         }
6521         
6522         
6523         freeAsmop(left,NULL,ic,TRUE);
6524         freeAsmop(result,NULL,ic,TRUE);
6525 }
6526
6527 /*-----------------------------------------------------------------*/
6528 /* genGetHbit - generates code get highest order bit               */
6529 /*-----------------------------------------------------------------*/
6530 static void genGetHbit (iCode *ic)
6531 {
6532         operand *left, *result;
6533         left = IC_LEFT(ic);
6534         result=IC_RESULT(ic);
6535         aopOp (left,ic,FALSE);
6536         aopOp (result,ic,FALSE);
6537         
6538         FENTRY;
6539         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6540         /* get the highest order byte into a */
6541         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6542         if(AOP_TYPE(result) == AOP_CRY){
6543                 pic14_emitcode("rlc","a");
6544                 pic14_outBitC(result);
6545         }
6546         else{
6547                 pic14_emitcode("rl","a");
6548                 pic14_emitcode("anl","a,#0x01");
6549                 pic14_outAcc(result);
6550         }
6551         
6552         
6553         freeAsmop(left,NULL,ic,TRUE);
6554         freeAsmop(result,NULL,ic,TRUE);
6555 }
6556
6557 /*-----------------------------------------------------------------*/
6558 /* AccRol - rotate left accumulator by known count                 */
6559 /*-----------------------------------------------------------------*/
6560 static void AccRol (operand *op,int offset,int shCount)
6561 {
6562         FENTRY;
6563         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6564         shCount &= 0x0007;              // shCount : 0..7
6565         switch(shCount){
6566         case 0 :
6567                 break;
6568         case 1 :
6569                 pic14_emitcode("rl","a");
6570                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6571                 break;
6572         case 2 :
6573                 pic14_emitcode("rl","a");
6574                 pic14_emitcode("rl","a");
6575                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6576                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6577                 break;
6578         case 3 :
6579                 pic14_emitcode("swap","a");
6580                 pic14_emitcode("rr","a");
6581                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6582                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6583                 break;
6584         case 4 :
6585                 pic14_emitcode("swap","a");
6586                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6587                 break;
6588         case 5 :
6589                 pic14_emitcode("swap","a");
6590                 pic14_emitcode("rl","a");
6591                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6592                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6593                 break;
6594         case 6 :
6595                 pic14_emitcode("rr","a");
6596                 pic14_emitcode("rr","a");
6597                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6598                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6599                 break;
6600         case 7 :
6601                 pic14_emitcode("rr","a");
6602                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6603                 break;
6604         }
6605 }
6606
6607 /*-----------------------------------------------------------------*/
6608 /* AccLsh - left shift accumulator by known count                  */
6609 /*-----------------------------------------------------------------*/
6610 static void AccLsh (operand *op,int offset,int shCount)
6611 {
6612         FENTRY;
6613         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6614         if(shCount != 0) {
6615                 if (shCount == 1)
6616                 {
6617                         emitCLRC;
6618                         emitpcode (POC_RLF, popGet (AOP(op), 0));
6619                 } else {
6620                         /* rotate left accumulator */
6621                         AccRol(op,offset,shCount);
6622                         /* and kill the lower order bits */
6623                         emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
6624                         emitpcode (POC_ANDWF, popGet (AOP(op),0));
6625                 }
6626         }
6627 }
6628
6629 /*-----------------------------------------------------------------*/
6630 /* AccRsh - right shift accumulator by known count                 */
6631 /*-----------------------------------------------------------------*/
6632 static void AccRsh (operand *op,int offset,int shCount)
6633 {
6634         FENTRY;
6635         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6636         if(shCount != 0){
6637                 if(shCount == 1){
6638                         emitCLRC;
6639                         emitpcode (POC_RRF, popGet (AOP(op), 0));
6640                 } else {
6641                         /* rotate right accumulator */
6642                         AccRol(op,offset,8 - shCount);
6643                         /* and kill the higher order bits */
6644                         emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
6645                         emitpcode (POC_ANDWF, popGet (AOP(op),0));
6646                 }
6647         }
6648 }
6649
6650 #if 0
6651 /*-----------------------------------------------------------------*/
6652 /* AccSRsh - signed right shift accumulator by known count                 */
6653 /*-----------------------------------------------------------------*/
6654 static void AccSRsh (int shCount)
6655 {
6656         symbol *tlbl ;
6657         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6658         if(shCount != 0){
6659                 if(shCount == 1){
6660                         pic14_emitcode("mov","c,acc.7");
6661                         pic14_emitcode("rrc","a");
6662                 } else if(shCount == 2){
6663                         pic14_emitcode("mov","c,acc.7");
6664                         pic14_emitcode("rrc","a");
6665                         pic14_emitcode("mov","c,acc.7");
6666                         pic14_emitcode("rrc","a");
6667                 } else {
6668                         tlbl = newiTempLabel(NULL);
6669                         /* rotate right accumulator */
6670                         AccRol(8 - shCount);
6671                         /* and kill the higher order bits */
6672                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6673                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6674                         pic14_emitcode("orl","a,#0x%02x",
6675                                 (unsigned char)~SRMask[shCount]);
6676                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6677                 }
6678         }
6679 }
6680
6681 /*-----------------------------------------------------------------*/
6682 /* shiftR1Left2Result - shift right one byte from left to result   */
6683 /*-----------------------------------------------------------------*/
6684 static void shiftR1Left2ResultSigned (operand *left, int offl,
6685                                                                           operand *result, int offr,
6686                                                                           int shCount)
6687 {
6688         int same;
6689         
6690         FENTRY;
6691         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6692         
6693         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6694         
6695         switch(shCount) {
6696         case 1:
6697                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6698                 if(same) 
6699                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6700                 else {
6701                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6702                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6703                 }
6704                 
6705                 break;
6706         case 2:
6707                 
6708                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6709                 if(same) 
6710                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6711                 else {
6712                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6713                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6714                 }
6715                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6716                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6717                 
6718                 break;
6719                 
6720         case 3:
6721                 if(same)
6722                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6723                 else {
6724                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6725                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6726                 }
6727                 
6728                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6729                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6730                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6731                 
6732                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6733                 emitpcode(POC_IORLW, popGetLit(0xe0));
6734                 
6735                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6736                 break;
6737                 
6738         case 4:
6739                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6740                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6741                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6742                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6743                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6744                 break;
6745         case 5:
6746                 if(same) {
6747                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6748                 } else {
6749                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6750                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6751                 }
6752                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6753                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6754                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6755                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6756                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6757                 break;
6758                 
6759         case 6:
6760                 if(same) {
6761                         emitpcode(POC_MOVLW, popGetLit(0x00));
6762                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6763                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6764                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6765                         emitpcode(POC_IORLW, popGetLit(0x01));
6766                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6767                 } else {
6768                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6769                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6770                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6771                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6772                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6773                 }
6774                 break;
6775                 
6776         case 7:
6777                 if(same) {
6778                         emitpcode(POC_MOVLW, popGetLit(0x00));
6779                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6780                         emitpcode(POC_MOVLW, popGetLit(0xff));
6781                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6782                 } else {
6783                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6784                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6785                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6786                 }
6787                 
6788         default:
6789                 break;
6790         }
6791 }
6792
6793 /*-----------------------------------------------------------------*/
6794 /* shiftR1Left2Result - shift right one byte from left to result   */
6795 /*-----------------------------------------------------------------*/
6796 static void shiftR1Left2Result (operand *left, int offl,
6797                                                                 operand *result, int offr,
6798                                                                 int shCount, int sign)
6799 {
6800         int same;
6801         
6802         FENTRY;
6803         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6804         
6805         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6806         
6807         /* Copy the msb into the carry if signed. */
6808         if(sign) {
6809                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6810                 return;
6811         }
6812         
6813         
6814         
6815         switch(shCount) {
6816         case 1:
6817                 emitCLRC;
6818                 if(same) 
6819                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6820                 else {
6821                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6822                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6823                 }
6824                 break;
6825         case 2:
6826                 emitCLRC;
6827                 if(same) {
6828                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6829                 } else {
6830                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6831                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6832                 }
6833                 emitCLRC;
6834                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6835                 
6836                 break;
6837         case 3:
6838                 if(same)
6839                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6840                 else {
6841                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6842                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6843                 }
6844                 
6845                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6846                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6847                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6848                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6849                 break;
6850                 
6851         case 4:
6852                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6853                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6854                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6855                 break;
6856                 
6857         case 5:
6858                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6859                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6860                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6861                 emitCLRC;
6862                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6863                 
6864                 break;
6865         case 6:
6866                 
6867                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6868                 emitpcode(POC_ANDLW, popGetLit(0x80));
6869                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6870                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6871                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6872                 break;
6873                 
6874         case 7:
6875                 
6876                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6877                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6878                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6879                 
6880                 break;
6881                 
6882         default:
6883                 break;
6884         }
6885 }
6886
6887 /*-----------------------------------------------------------------*/
6888 /* shiftL1Left2Result - shift left one byte from left to result    */
6889 /*-----------------------------------------------------------------*/
6890 static void shiftL1Left2Result (operand *left, int offl,
6891                                                                 operand *result, int offr, int shCount)
6892 {
6893         int same;
6894         
6895         //    char *l;
6896         FENTRY;
6897         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6898         
6899         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6900         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6901         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6902         //    MOVA(l);
6903         /* shift left accumulator */
6904         //AccLsh(shCount); // don't comment out just yet...
6905         //    aopPut(AOP(result),"a",offr);
6906         
6907         switch(shCount) {
6908         case 1:
6909                 /* Shift left 1 bit position */
6910                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6911                 if(same) {
6912                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6913                 } else {
6914                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6915                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6916                 }
6917                 break;
6918         case 2:
6919                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6920                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6921                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6922                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6923                 break;
6924         case 3:
6925                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6926                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6927                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6928                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6929                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6930                 break;
6931         case 4:
6932                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6933                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6934                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6935                 break;
6936         case 5:
6937                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6938                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6939                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6940                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6941                 break;
6942         case 6:
6943                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6944                 emitpcode(POC_ANDLW, popGetLit(0x30));
6945                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6946                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6947                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6948                 break;
6949         case 7:
6950                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6951                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6952                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6953                 break;
6954                 
6955         default:
6956                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6957         }
6958         
6959 }
6960 #endif
6961
6962 /*-----------------------------------------------------------------*/
6963 /* movLeft2Result - move byte from left to result                  */
6964 /*-----------------------------------------------------------------*/
6965 static void movLeft2Result (operand *left, int offl,
6966                                                         operand *result, int offr)
6967 {
6968         char *l;
6969         FENTRY;
6970         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6971         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6972                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6973                 
6974                 if (*l == '@' && (IS_AOP_PREG(result))) {
6975                         pic14_emitcode("mov","a,%s",l);
6976                         aopPut(AOP(result),"a",offr);
6977                 } else {
6978                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6979                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6980                 }
6981         }
6982 }
6983
6984 /*-----------------------------------------------------------------*/
6985 /* shiftLeft_Left2ResultLit - shift left by known count            */
6986 /*-----------------------------------------------------------------*/
6987
6988 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6989 {
6990         int size, same, offr, i;
6991
6992         size = AOP_SIZE(left);
6993         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6994         
6995         same = pic14_sameRegs (AOP(left), AOP(result));
6996         
6997         offr = shCount / 8;
6998         shCount = shCount & 0x07;
6999
7000         size -= offr;
7001
7002         switch (shCount)
7003         {
7004         case 0: /* takes 0 or 2N cycles (for offr==0) */
7005                 if (!same || offr) {
7006                         for (i=size-1; i >= 0; i--)
7007                                 movLeft2Result (left, i, result, offr + i);
7008                 } // if
7009                 break;
7010                 
7011         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
7012                 if (same && offr) {
7013                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
7014                         shiftLeft_Left2ResultLit (result, result, shCount);
7015                         return; /* prevent clearing result again */
7016                 } else {
7017                         emitCLRC;
7018                         for (i=0; i < size; i++) {
7019                                 if (same && !offr) {
7020                                         emitpcode (POC_RLF, popGet (AOP(left), i));
7021                                 } else {
7022                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
7023                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7024                                 } // if
7025                         } // for
7026                 } // if (offr)
7027                 break;
7028                 
7029         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7030                 /* works in-place/with offr as well */
7031                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7032                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7033                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7034
7035                 for (i = size - 2; i >= 0; i--)
7036                 {
7037                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7038                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7039                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7040                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7041                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7042                 } // for i
7043                 break;
7044                 
7045         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7046                 /* works in-place/with offr as well */
7047                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7048                 for (i = size-2; i >= 0; i--) {
7049                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7050                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7051                 } // for i
7052                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7053                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7054                 break;
7055         
7056         default:
7057                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7058                 shiftLeft_Left2ResultLit (result, result, 1);
7059                 return; /* prevent clearing result again */
7060                 break;
7061         } // switch
7062
7063         while (0 < offr--)
7064         {
7065                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7066         } // while
7067 }
7068
7069 /*-----------------------------------------------------------------*/
7070 /* shiftRight_Left2ResultLit - shift right by known count          */
7071 /*-----------------------------------------------------------------*/
7072
7073 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7074 {
7075         int size, same, offr, i;
7076
7077         size = AOP_SIZE(left);
7078         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7079         
7080         same = pic14_sameRegs (AOP(left), AOP(result));
7081         
7082         offr = shCount / 8;
7083         shCount = shCount & 0x07;
7084
7085         size -= offr;
7086
7087         if (size)
7088         {
7089                 switch (shCount)
7090                 {
7091                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7092                         if (!same || offr) {
7093                                 for (i=0; i < size; i++)
7094                                         movLeft2Result (left, i + offr, result, i);
7095                         } // if
7096                         break;
7097                         
7098                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7099                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7100                         if (same && offr) {
7101                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7102                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7103                                 return; /* prevent sign-extending result again */
7104                         } else {
7105                                 emitCLRC;
7106                                 if (sign) {
7107                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7108                                         emitSETC;
7109                                 }
7110                                 for (i = size-1; i >= 0; i--) {
7111                                         if (same && !offr) {
7112                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7113                                         } else {
7114                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7115                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7116                                         }
7117                                 } // for i
7118                         } // if (offr)
7119                         break;
7120                         
7121                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7122                         /* works in-place/with offr as well */
7123                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7124                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7125                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7126
7127                         for (i = 1; i < size; i++)
7128                         {
7129                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7130                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7131                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7132                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7133                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7134                         } // for i
7135
7136                         if (sign)
7137                         {
7138                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7139                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7140                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7141                         } // if
7142                         break;
7143                         
7144                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7145                         /* works in-place/with offr as well */
7146                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7147                         for (i = 0; i < size-1; i++) {
7148                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7149                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7150                         } // for i
7151                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7152                         if (!sign) {
7153                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7154                         } else {
7155                                 emitSKPNC;
7156                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7157                         }
7158                         break;
7159                 
7160                 default:
7161                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7162                         shiftRight_Left2ResultLit (result, result, 1, sign);
7163                         return; /* prevent sign extending result again */
7164                         break;
7165                 } // switch
7166         } // if
7167
7168         addSign (result, size, sign);
7169 }
7170
7171 #if 0
7172 /*-----------------------------------------------------------------*/
7173 /* shiftL2Left2Result - shift left two bytes from left to result   */
7174 /*-----------------------------------------------------------------*/
7175 static void shiftL2Left2Result (operand *left, int offl,
7176                                                                 operand *result, int offr, int shCount)
7177 {
7178         FENTRY;
7179         
7180         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7181         
7182         if(pic14_sameRegs(AOP(result), AOP(left))) {
7183                 switch(shCount) {
7184                 case 0:
7185                         break;
7186                 case 1:
7187                 case 2:
7188                 case 3:
7189                         
7190                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7191                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7192                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7193                         
7194                         while(--shCount) {
7195                                 emitCLRC;
7196                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7197                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7198                         }
7199                         
7200                         break;
7201                 case 4:
7202                 case 5:
7203                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7204                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7205                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7206                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7207                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7208                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7209                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7210                         if(shCount >=5) {
7211                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7212                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7213                         }
7214                         break;
7215                 case 6:
7216                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7217                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7218                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7219                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7220                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7221                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7222                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7223                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7224                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7225                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7226                         break;
7227                 case 7:
7228                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7229                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7230                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7231                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7232                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7233                 }
7234                 
7235         } else {
7236                 switch(shCount) {
7237                 case 0:
7238                         break;
7239                 case 1:
7240                 case 2:
7241                 case 3:
7242                 /* note, use a mov/add for the shift since the mov has a
7243                         chance of getting optimized out */
7244                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7245                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7246                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7247                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7248                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7249                         
7250                         while(--shCount) {
7251                                 emitCLRC;
7252                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7253                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7254                         }
7255                         break;
7256                         
7257                 case 4:
7258                 case 5:
7259                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7260                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7261                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7262                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7263                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7264                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7265                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7266                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7267                         
7268                         
7269                         if(shCount == 5) {
7270                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7271                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7272                         }
7273                         break;
7274                 case 6:
7275                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7276                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7277                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7278                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7279                         
7280                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7281                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7282                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7283                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7284                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7285                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7286                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7287                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7288                         break;
7289                 case 7:
7290                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7291                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7292                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7293                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7294                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7295                 }
7296         }
7297         
7298 }
7299
7300 /*-----------------------------------------------------------------*/
7301 /* shiftR2Left2Result - shift right two bytes from left to result  */
7302 /*-----------------------------------------------------------------*/
7303 static void shiftR2Left2Result (operand *left, int offl,
7304                                                                 operand *result, int offr,
7305                                                                 int shCount, int sign)
7306 {
7307         int same=0;
7308         
7309         FENTRY;
7310         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7311         same = pic14_sameRegs(AOP(result), AOP(left));
7312         
7313         if(same && ((offl + MSB16) == offr)){
7314                 same=1;
7315                 /* don't crash result[offr] */
7316                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7317                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7318         }
7319         /* else {
7320         movLeft2Result(left,offl, result, offr);
7321         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7322         }
7323         */
7324         /* a:x >> shCount (x = lsb(result))*/
7325         /*
7326         if(sign)
7327         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7328         else {
7329         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7330         */
7331         switch(shCount) {
7332         case 0:
7333                 break;
7334         case 1:
7335         case 2:
7336         case 3:
7337                 if(sign)
7338                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7339                 else
7340                         emitCLRC;
7341                 
7342                 if(same) {
7343                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7344                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7345                 } else {
7346                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7347                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7348                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7349                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7350                 }
7351                 
7352                 while(--shCount) {
7353                         if(sign)
7354                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7355                         else
7356                                 emitCLRC;
7357                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7358                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7359                 }
7360                 break;
7361         case 4:
7362         case 5:
7363                 if(same) {
7364                         
7365                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7366                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7367                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7368                         
7369                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7370                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7371                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7372                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7373                 } else {
7374                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7375                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7376                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7377                         
7378                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7379                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7380                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7381                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7382                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7383                 }
7384                 
7385                 if(shCount >=5) {
7386                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7387                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7388                 }
7389                 
7390                 if(sign) {
7391                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7392                         emitpcode(POC_BTFSC, 
7393                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7394                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7395                 }
7396                 
7397                 break;
7398                 
7399         case 6:
7400                 if(same) {
7401                         
7402                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7403                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7404                         
7405                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7406                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7407                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7408                         emitpcode(POC_ANDLW,popGetLit(0x03));
7409                         if(sign) {
7410                                 emitpcode(POC_BTFSC, 
7411                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7412                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7413                         }
7414                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7415                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7416                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7417                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7418                 } else {
7419                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7420                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7421                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7422                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7423                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7424                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7425                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7426                         emitpcode(POC_ANDLW,popGetLit(0x03));
7427                         if(sign) {
7428                                 emitpcode(POC_BTFSC, 
7429                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7430                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7431                         }
7432                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7433                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7434                         
7435                         
7436                 }
7437                 
7438                 break;
7439         case 7:
7440                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7441                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7442                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7443                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7444                 if(sign) {
7445                         emitSKPNC;
7446                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7447                 } else 
7448                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7449   }
7450 }
7451
7452 /*-----------------------------------------------------------------*/
7453 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7454 /*-----------------------------------------------------------------*/
7455 static void shiftLLeftOrResult (operand *left, int offl,
7456                                                                 operand *result, int offr, int shCount)
7457 {
7458         FENTRY;
7459         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7460         
7461         /* shift left accumulator */
7462         AccLsh(left,offl,shCount);
7463         /* or with result */
7464         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7465         assert ( !"broken (modifies left, fails for left==result))" );
7466 }
7467
7468 /*-----------------------------------------------------------------*/
7469 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7470 /*-----------------------------------------------------------------*/
7471 static void shiftRLeftOrResult (operand *left, int offl,
7472                                                                 operand *result, int offr, int shCount)
7473 {
7474         FENTRY;
7475         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7476         
7477         /* shift right accumulator */
7478         AccRsh(left,offl,shCount);
7479         /* or with result */
7480         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7481         assert ( !"broken (modifies left, fails for left==result))" );
7482 }
7483
7484 /*-----------------------------------------------------------------*/
7485 /* genlshOne - left shift a one byte quantity by known count       */
7486 /*-----------------------------------------------------------------*/
7487 static void genlshOne (operand *result, operand *left, int shCount)
7488 {       
7489         FENTRY;
7490         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7491         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7492 }
7493
7494 /*-----------------------------------------------------------------*/
7495 /* genlshTwo - left shift two bytes by known amount != 0           */
7496 /*-----------------------------------------------------------------*/
7497 static void genlshTwo (operand *result,operand *left, int shCount)
7498 {
7499         int size;
7500         
7501         FENTRY;
7502         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7503         size = pic14_getDataSize(result);
7504         
7505         /* if shCount >= 8 */
7506         if (shCount >= 8) {
7507                 shCount -= 8 ;
7508                 
7509                 if (size > 1){
7510                         if (shCount)
7511                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7512                         else 
7513                                 movLeft2Result(left, LSB, result, MSB16);
7514                 }
7515                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7516         }
7517         
7518         /*  1 <= shCount <= 7 */
7519         else {  
7520                 if(size == 1)
7521                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7522                 else 
7523                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7524         }
7525 }
7526
7527 /*-----------------------------------------------------------------*/
7528 /* shiftLLong - shift left one long from left to result            */
7529 /* offl = LSB or MSB16                                             */
7530 /*-----------------------------------------------------------------*/
7531 static void shiftLLong (operand *left, operand *result, int offr )
7532 {
7533         char *l;
7534         int size = AOP_SIZE(result);
7535         
7536         FENTRY;
7537         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7538         if(size >= LSB+offr){
7539                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7540                 MOVA(l);
7541                 pic14_emitcode("add","a,acc");
7542                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7543                         size >= MSB16+offr && offr != LSB )
7544                         pic14_emitcode("xch","a,%s",
7545                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7546                 else      
7547                         aopPut(AOP(result),"a",LSB+offr);
7548         }
7549         
7550         if(size >= MSB16+offr){
7551                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7552                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7553                         MOVA(l);
7554                 }
7555                 pic14_emitcode("rlc","a");
7556                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7557                         size >= MSB24+offr && offr != LSB)
7558                         pic14_emitcode("xch","a,%s",
7559                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7560                 else      
7561                         aopPut(AOP(result),"a",MSB16+offr);
7562         }
7563         
7564         if(size >= MSB24+offr){
7565                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7566                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7567                         MOVA(l);
7568                 }
7569                 pic14_emitcode("rlc","a");
7570                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7571                         size >= MSB32+offr && offr != LSB )
7572                         pic14_emitcode("xch","a,%s",
7573                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7574                 else      
7575                         aopPut(AOP(result),"a",MSB24+offr);
7576         }
7577         
7578         if(size > MSB32+offr){
7579                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7580                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7581                         MOVA(l);  
7582                 }
7583                 pic14_emitcode("rlc","a");
7584                 aopPut(AOP(result),"a",MSB32+offr);
7585         }
7586         if(offr != LSB)
7587                 aopPut(AOP(result),zero,LSB);       
7588 }
7589
7590 /*-----------------------------------------------------------------*/
7591 /* genlshFour - shift four byte by a known amount != 0             */
7592 /*-----------------------------------------------------------------*/
7593 static void genlshFour (operand *result, operand *left, int shCount)
7594 {
7595         int size;
7596         
7597         FENTRY;
7598         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7599         size = AOP_SIZE(result);
7600         
7601         /* if shifting more that 3 bytes */
7602         if (shCount >= 24 ) {
7603                 shCount -= 24;
7604                 if (shCount)
7605                 /* lowest order of left goes to the highest
7606                 order of the destination */
7607                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7608                 else
7609                         movLeft2Result(left, LSB, result, MSB32);
7610                 aopPut(AOP(result),zero,LSB);
7611                 aopPut(AOP(result),zero,MSB16);
7612                 aopPut(AOP(result),zero,MSB32);
7613                 return;
7614         }
7615         
7616         /* more than two bytes */
7617         else if ( shCount >= 16 ) {
7618                 /* lower order two bytes goes to higher order two bytes */
7619                 shCount -= 16;
7620                 /* if some more remaining */
7621                 if (shCount)
7622                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7623                 else {
7624                         movLeft2Result(left, MSB16, result, MSB32);
7625                         movLeft2Result(left, LSB, result, MSB24);
7626                 }
7627                 aopPut(AOP(result),zero,MSB16);
7628                 aopPut(AOP(result),zero,LSB);
7629                 return;
7630         }    
7631         
7632         /* if more than 1 byte */
7633         else if ( shCount >= 8 ) {
7634                 /* lower order three bytes goes to higher order  three bytes */
7635                 shCount -= 8;
7636                 if(size == 2){
7637                         if(shCount)
7638                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7639                         else
7640                                 movLeft2Result(left, LSB, result, MSB16);
7641                 }
7642                 else{   /* size = 4 */
7643                         if(shCount == 0){
7644                                 movLeft2Result(left, MSB24, result, MSB32);
7645                                 movLeft2Result(left, MSB16, result, MSB24);
7646                                 movLeft2Result(left, LSB, result, MSB16);
7647                                 aopPut(AOP(result),zero,LSB);
7648                         }
7649                         else if(shCount == 1)
7650                                 shiftLLong(left, result, MSB16);
7651                         else{
7652                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7653                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7654                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7655                                 aopPut(AOP(result),zero,LSB);
7656                         }
7657                 }
7658         }
7659         
7660         /* 1 <= shCount <= 7 */
7661         else if(shCount <= 2){
7662                 shiftLLong(left, result, LSB);
7663                 if(shCount == 2)
7664                         shiftLLong(result, result, LSB);
7665         }
7666         /* 3 <= shCount <= 7, optimize */
7667         else{
7668                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7669                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7670                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7671         }
7672 }
7673 #endif
7674
7675 #if 0
7676 /*-----------------------------------------------------------------*/
7677 /* genLeftShiftLiteral - left shifting by known count              */
7678 /*-----------------------------------------------------------------*/
7679 static void genLeftShiftLiteral (operand *left,
7680                                                                  operand *right,
7681                                                                  operand *result,
7682                                                                  iCode *ic)
7683 {    
7684         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7685         //int size;
7686         
7687         FENTRY;
7688         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7689         freeAsmop(right,NULL,ic,TRUE);
7690         
7691         aopOp(left,ic,FALSE);
7692         aopOp(result,ic,FALSE);
7693
7694         size = getSize(operandType(result));
7695         
7696 #if VIEW_SIZE
7697         pic14_emitcode("; shift left ","result %d, left %d",size,
7698                 AOP_SIZE(left));
7699 #endif
7700         
7701         /* I suppose that the left size >= result size */
7702         if(shCount == 0){
7703                 while(size--){
7704                         movLeft2Result(left, size, result, size);
7705                 }
7706         }
7707         
7708         else if(shCount >= (size * 8))
7709                 while(size--)
7710                         aopPut(AOP(result),zero,size);
7711                 else{
7712                         switch (size) {
7713                         case 1:
7714                                 genlshOne (result,left,shCount);
7715                                 break;
7716                                 
7717                         case 2:
7718                         case 3:
7719                                 genlshTwo (result,left,shCount);
7720                                 break;
7721                                 
7722                         case 4:
7723                                 genlshFour (result,left,shCount);
7724                                 break;
7725                         }
7726                 }
7727                 freeAsmop(left,NULL,ic,TRUE);
7728                 freeAsmop(result,NULL,ic,TRUE);
7729 }
7730 #endif
7731
7732 /*-----------------------------------------------------------------*
7733 * genMultiAsm - repeat assembly instruction for size of register.
7734 * if endian == 1, then the high byte (i.e base address + size of 
7735 * register) is used first else the low byte is used first;
7736 *-----------------------------------------------------------------*/
7737 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7738 {
7739         
7740         int offset = 0;
7741         
7742         FENTRY;
7743         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7744         
7745         if(!reg)
7746                 return;
7747         
7748         if(!endian) {
7749                 endian = 1;
7750         } else {
7751                 endian = -1;
7752                 offset = size-1;
7753         }
7754         
7755         while(size--) {
7756                 emitpcode(poc,    popGet(AOP(reg),offset));
7757                 offset += endian;
7758         }
7759         
7760 }
7761 /*-----------------------------------------------------------------*/
7762 /* genLeftShift - generates code for left shifting                 */
7763 /*-----------------------------------------------------------------*/
7764 static void genLeftShift (iCode *ic)
7765 {
7766         operand *left,*right, *result;
7767         int size, offset;
7768         unsigned long lit = 0L;
7769         char *l;
7770         symbol *tlbl , *tlbl1;
7771         pCodeOp *pctemp;
7772         
7773         FENTRY;
7774         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7775         
7776         right = IC_RIGHT(ic);
7777         left  = IC_LEFT(ic);
7778         result = IC_RESULT(ic);
7779         
7780         aopOp(right,ic,FALSE);
7781         aopOp(left,ic,FALSE);
7782         aopOp(result,ic,FALSE);
7783         
7784         
7785         /* if the shift count is known then do it 
7786         as efficiently as possible */
7787         if (AOP_TYPE(right) == AOP_LIT) {
7788                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7789                 return ;
7790         }
7791         
7792         /* shift count is unknown then we have to form 
7793         a loop get the loop count in B : Note: we take
7794         only the lower order byte since shifting
7795         more that 32 bits make no sense anyway, ( the
7796         largest size of an object can be only 32 bits ) */  
7797         
7798         /* this code fails for RIGHT == RESULT */
7799         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7800         
7801         /* now move the left to the result if they are not the
7802         same */
7803         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7804                 AOP_SIZE(result) > 1) {
7805                 
7806                 size = AOP_SIZE(result);
7807                 offset=0;
7808                 while (size--) {
7809                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7810                         if (*l == '@' && (IS_AOP_PREG(result))) {
7811                                 
7812                                 pic14_emitcode("mov","a,%s",l);
7813                                 aopPut(AOP(result),"a",offset);
7814                         } else {
7815                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7816                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7817                                 //aopPut(AOP(result),l,offset);
7818                         }
7819                         offset++;
7820                 }
7821         }
7822         
7823         if(AOP_TYPE(left) == AOP_LIT)
7824                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7825
7826         size = AOP_SIZE(result);
7827         
7828         /* if it is only one byte then */
7829         if (size == 1) {
7830                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7831                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7832                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7833                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7834                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7835                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7836                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7837                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7838                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7839                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7840                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7841                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7842                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7843                 } else {
7844                         
7845                         tlbl = newiTempLabel(NULL);
7846                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7847                                 mov2w (AOP(left), 0);
7848                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7849                         }
7850                         
7851                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7852                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7853                         emitpLabel(tlbl->key);
7854                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7855                         emitpcode(POC_ADDLW,  popGetLit(1));
7856                         emitSKPC;
7857                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7858                 }
7859                 goto release ;
7860         }
7861         
7862         if (pic14_sameRegs(AOP(left),AOP(result))) {
7863                 
7864                 tlbl = newiTempLabel(NULL);
7865                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7866                 genMultiAsm(POC_RRF, result, size,1);
7867                 emitpLabel(tlbl->key);
7868                 genMultiAsm(POC_RLF, result, size,0);
7869                 emitpcode(POC_ADDLW,  popGetLit(1));
7870                 emitSKPC;
7871                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7872                 goto release;
7873         }
7874         
7875         //tlbl = newiTempLabel(NULL);
7876         //offset = 0 ;   
7877         //tlbl1 = newiTempLabel(NULL);
7878         
7879         //reAdjustPreg(AOP(result));    
7880         
7881         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7882         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7883         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7884         //MOVA(l);
7885         //pic14_emitcode("add","a,acc");         
7886         //aopPut(AOP(result),"a",offset++);
7887         //while (--size) {
7888         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7889         //  MOVA(l);
7890         //  pic14_emitcode("rlc","a");         
7891         //  aopPut(AOP(result),"a",offset++);
7892         //}
7893         //reAdjustPreg(AOP(result));
7894         
7895         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7896         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7897         
7898         
7899         tlbl = newiTempLabel(NULL);
7900         tlbl1= newiTempLabel(NULL);
7901         
7902         size = AOP_SIZE(result);
7903         offset = 1;
7904         
7905         pctemp = popGetTempReg();  /* grab a temporary working register. */
7906         
7907         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7908         
7909         /* offset should be 0, 1 or 3 */
7910         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7911         emitSKPNZ;
7912         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7913         
7914         emitpcode(POC_MOVWF, pctemp);
7915         
7916         
7917         emitpLabel(tlbl->key);
7918         
7919         emitCLRC;
7920         emitpcode(POC_RLF,  popGet(AOP(result),0));
7921         while(--size)
7922                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7923         
7924         emitpcode(POC_DECFSZ,  pctemp);
7925         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7926         emitpLabel(tlbl1->key);
7927         
7928         popReleaseTempReg(pctemp);
7929         
7930         
7931 release:
7932         freeAsmop (right,NULL,ic,TRUE);
7933         freeAsmop(left,NULL,ic,TRUE);
7934         freeAsmop(result,NULL,ic,TRUE);
7935 }
7936
7937 #if 0
7938 /*-----------------------------------------------------------------*/
7939 /* genrshOne - right shift a one byte quantity by known count      */
7940 /*-----------------------------------------------------------------*/
7941 static void genrshOne (operand *result, operand *left,
7942                                            int shCount, int sign)
7943 {
7944         FENTRY;
7945         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7946         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7947 }
7948
7949 /*-----------------------------------------------------------------*/
7950 /* genrshTwo - right shift two bytes by known amount != 0          */
7951 /*-----------------------------------------------------------------*/
7952 static void genrshTwo (operand *result,operand *left,
7953                                            int shCount, int sign)
7954 {
7955         FENTRY;
7956         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7957         /* if shCount >= 8 */
7958         if (shCount >= 8) {
7959                 shCount -= 8 ;
7960                 if (shCount)
7961                         shiftR1Left2Result(left, MSB16, result, LSB,
7962                         shCount, sign);
7963                 else
7964                         movLeft2Result(left, MSB16, result, LSB);
7965                 
7966                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7967                 
7968                 if(sign) {
7969                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7970                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7971                 }
7972         }
7973         
7974         /*  1 <= shCount <= 7 */
7975         else
7976                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7977 }
7978
7979 /*-----------------------------------------------------------------*/
7980 /* shiftRLong - shift right one long from left to result           */
7981 /* offl = LSB or MSB16                                             */
7982 /*-----------------------------------------------------------------*/
7983 static void shiftRLong (operand *left, int offl,
7984                                                 operand *result, int sign)
7985 {
7986         int size, same;
7987         
7988         FENTRY;
7989         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7990         
7991         size = AOP_SIZE(left);
7992         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7993         
7994         if (sign)
7995                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7996         else
7997                 emitCLRC;
7998
7999         assert (offl >= 0 && offl < size);
8000
8001         same = pic14_sameRegs (AOP(left), AOP(result));
8002
8003         /* perform the shift */
8004         while (size--)
8005         {
8006                 if (same && !offl) {
8007                         emitpcode (POC_RRF, popGet (AOP(result), size));
8008                 } else {
8009                         emitpcode (POC_RRFW, popGet (AOP(left), size));
8010                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
8011                 }
8012         } // while
8013
8014         addSign (result, AOP_SIZE(left) - offl, sign);
8015 }
8016
8017 /*-----------------------------------------------------------------*/
8018 /* genrshFour - shift four byte by a known amount != 0             */
8019 /*-----------------------------------------------------------------*/
8020 static void genrshFour (operand *result, operand *left,
8021                                                 int shCount, int sign)
8022 {
8023         FENTRY;
8024         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8025         /* if shifting more that 3 bytes */
8026         if(shCount >= 24 ) {
8027                 shCount -= 24;
8028                 if(shCount)
8029                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8030                 else
8031                         movLeft2Result(left, MSB32, result, LSB);
8032                 
8033                 addSign(result, MSB16, sign);
8034         }
8035         else if(shCount >= 16){
8036                 shCount -= 16;
8037                 if(shCount)
8038                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8039                 else{
8040                         movLeft2Result(left, MSB24, result, LSB);
8041                         movLeft2Result(left, MSB32, result, MSB16);
8042                 }
8043                 addSign(result, MSB24, sign);
8044         }
8045         else if(shCount >= 8){
8046                 shCount -= 8;
8047                 if(shCount == 1)
8048                         shiftRLong(left, MSB16, result, sign);
8049                 else if(shCount == 0){
8050                         movLeft2Result(left, MSB16, result, LSB);
8051                         movLeft2Result(left, MSB24, result, MSB16);
8052                         movLeft2Result(left, MSB32, result, MSB24);
8053                         addSign(result, MSB32, sign);
8054                 }
8055                 else{
8056                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8057                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8058                         /* the last shift is signed */
8059                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8060                         addSign(result, MSB32, sign);
8061                 }
8062         }
8063         else{   /* 1 <= shCount <= 7 */
8064                 if(shCount <= 2){
8065                         shiftRLong(left, LSB, result, sign);
8066                         if(shCount == 2)
8067                                 shiftRLong(result, LSB, result, sign);
8068                 }
8069                 else{
8070                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8071                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8072                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8073                 }
8074         }
8075 }
8076
8077 /*-----------------------------------------------------------------*/
8078 /* genRightShiftLiteral - right shifting by known count            */
8079 /*-----------------------------------------------------------------*/
8080 static void genRightShiftLiteral (operand *left,
8081                                                                   operand *right,
8082                                                                   operand *result,
8083                                                                   iCode *ic,
8084                                                                   int sign)
8085 {    
8086         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8087         int lsize,res_size;
8088         
8089         FENTRY;
8090         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8091         freeAsmop(right,NULL,ic,TRUE);
8092         
8093         aopOp(left,ic,FALSE);
8094         aopOp(result,ic,FALSE);
8095         
8096 #if VIEW_SIZE
8097         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8098                 AOP_SIZE(left));
8099 #endif
8100         
8101         lsize = pic14_getDataSize(left);
8102         res_size = pic14_getDataSize(result);
8103         /* test the LEFT size !!! */
8104         
8105         /* I suppose that the left size >= result size */
8106         if(shCount == 0){
8107                 while(res_size--)
8108                         movLeft2Result(left, res_size, result, res_size);
8109         }
8110         
8111         else if(shCount >= (lsize * 8)){
8112                 
8113                 if(res_size == 1) {
8114                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8115                         if(sign) {
8116                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8117                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8118                         }
8119                 } else {
8120                         
8121                         if(sign) {
8122                                 emitpcode(POC_MOVLW, popGetLit(0));
8123                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8124                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8125                                 while(res_size--)
8126                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8127                                 
8128                         } else {
8129                                 
8130                                 while(res_size--)
8131                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8132                         }
8133                 }
8134         } else {
8135                 
8136                 switch (res_size) {
8137                 case 1:
8138                         genrshOne (result,left,shCount,sign);
8139                         break;
8140                         
8141                 case 2:
8142                         genrshTwo (result,left,shCount,sign);
8143                         break;
8144                         
8145                 case 4:
8146                         genrshFour (result,left,shCount,sign);
8147                         break;
8148                 default :
8149                         break;
8150                 }
8151                 
8152         }
8153
8154         freeAsmop(left,NULL,ic,TRUE);
8155         freeAsmop(result,NULL,ic,TRUE);
8156 }
8157 #endif
8158
8159 /*-----------------------------------------------------------------*/
8160 /* genSignedRightShift - right shift of signed number              */
8161 /*-----------------------------------------------------------------*/
8162 static void genSignedRightShift (iCode *ic)
8163 {
8164         operand *right, *left, *result;
8165         int size, offset;
8166         //  char *l;
8167         symbol *tlbl, *tlbl1 ;
8168         pCodeOp *pctemp;
8169         
8170         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8171         
8172         /* we do it the hard way put the shift count in b
8173         and loop thru preserving the sign */
8174         FENTRY;
8175         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8176         
8177         right = IC_RIGHT(ic);
8178         left  = IC_LEFT(ic);
8179         result = IC_RESULT(ic);
8180         
8181         aopOp(right,ic,FALSE);  
8182         aopOp(left,ic,FALSE);
8183         aopOp(result,ic,FALSE);
8184         
8185         
8186         if ( AOP_TYPE(right) == AOP_LIT) {
8187                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8188                 //genRightShiftLiteral (left,right,result,ic,1);
8189                 return ;
8190         }
8191         /* shift count is unknown then we have to form 
8192         a loop get the loop count in B : Note: we take
8193         only the lower order byte since shifting
8194         more that 32 bits make no sense anyway, ( the
8195         largest size of an object can be only 32 bits ) */  
8196         
8197         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8198         //pic14_emitcode("inc","b");
8199         //freeAsmop (right,NULL,ic,TRUE);
8200         //aopOp(left,ic,FALSE);
8201         //aopOp(result,ic,FALSE);
8202         
8203         /* now move the left to the result if they are not the
8204         same */
8205         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8206                 AOP_SIZE(result) > 1) {
8207                 
8208                 size = AOP_SIZE(result);
8209                 offset=0;
8210                 while (size--) { 
8211                         /*
8212                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8213                         if (*l == '@' && IS_AOP_PREG(result)) {
8214                                 pic14_emitcode("mov","a,%s",l);
8215                                 aopPut(AOP(result),"a",offset);
8216                         } else
8217                         aopPut(AOP(result),l,offset);
8218                         */
8219                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8220                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8221                         
8222                         offset++;
8223                 }
8224         }
8225         
8226         /* mov the highest order bit to OVR */    
8227         tlbl = newiTempLabel(NULL);
8228         tlbl1= newiTempLabel(NULL);
8229         
8230         size = AOP_SIZE(result);
8231         offset = size - 1;
8232         
8233         pctemp = popGetTempReg();  /* grab a temporary working register. */
8234         
8235         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8236         
8237         /* offset should be 0, 1 or 3 */
8238         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8239         emitSKPNZ;
8240         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8241         
8242         emitpcode(POC_MOVWF, pctemp);
8243         
8244         
8245         emitpLabel(tlbl->key);
8246         
8247         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8248         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8249         
8250         while(--size) {
8251                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8252         }
8253         
8254         emitpcode(POC_DECFSZ,  pctemp);
8255         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8256         emitpLabel(tlbl1->key);
8257         
8258         popReleaseTempReg(pctemp);
8259 #if 0
8260         size = AOP_SIZE(result);
8261         offset = size - 1;
8262         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8263         pic14_emitcode("rlc","a");
8264         pic14_emitcode("mov","ov,c");
8265         /* if it is only one byte then */
8266         if (size == 1) {
8267                 l = aopGet(AOP(left),0,FALSE,FALSE);
8268                 MOVA(l);
8269                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8270                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8271                 pic14_emitcode("mov","c,ov");
8272                 pic14_emitcode("rrc","a");
8273                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8274                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8275                 aopPut(AOP(result),"a",0);
8276                 goto release ;
8277         }
8278         
8279         reAdjustPreg(AOP(result));
8280         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8281         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8282         pic14_emitcode("mov","c,ov");
8283         while (size--) {
8284                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8285                 MOVA(l);
8286                 pic14_emitcode("rrc","a");         
8287                 aopPut(AOP(result),"a",offset--);
8288         }
8289         reAdjustPreg(AOP(result));
8290         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8291         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8292         
8293 release:
8294 #endif
8295         
8296         freeAsmop(left,NULL,ic,TRUE);
8297         freeAsmop(result,NULL,ic,TRUE);
8298         freeAsmop(right,NULL,ic,TRUE);
8299 }
8300
8301 /*-----------------------------------------------------------------*/
8302 /* genRightShift - generate code for right shifting                */
8303 /*-----------------------------------------------------------------*/
8304 static void genRightShift (iCode *ic)
8305 {
8306         operand *right, *left, *result;
8307         sym_link *retype ;
8308         int size, offset;
8309         char *l;
8310         symbol *tlbl, *tlbl1 ;
8311         
8312         FENTRY;
8313         /* if signed then we do it the hard way preserve the
8314         sign bit moving it inwards */
8315         retype = getSpec(operandType(IC_RESULT(ic)));
8316         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8317         
8318         if (!SPEC_USIGN(retype)) {
8319                 genSignedRightShift (ic);
8320                 return ;
8321         }
8322         
8323         /* signed & unsigned types are treated the same : i.e. the
8324         signed is NOT propagated inwards : quoting from the
8325         ANSI - standard : "for E1 >> E2, is equivalent to division
8326         by 2**E2 if unsigned or if it has a non-negative value,
8327         otherwise the result is implementation defined ", MY definition
8328         is that the sign does not get propagated */
8329         
8330         right = IC_RIGHT(ic);
8331         left  = IC_LEFT(ic);
8332         result = IC_RESULT(ic);
8333         
8334         aopOp(right,ic,FALSE);
8335         aopOp(left,ic,FALSE);
8336         aopOp(result,ic,FALSE);
8337         
8338         /* if the shift count is known then do it 
8339         as efficiently as possible */
8340         if (AOP_TYPE(right) == AOP_LIT) {
8341                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
8342                 //genRightShiftLiteral (left,right,result,ic, 0);
8343                 return ;
8344         }
8345         
8346         /* shift count is unknown then we have to form 
8347         a loop get the loop count in B : Note: we take
8348         only the lower order byte since shifting
8349         more that 32 bits make no sense anyway, ( the
8350         largest size of an object can be only 32 bits ) */  
8351         
8352         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8353         pic14_emitcode("inc","b");
8354         
8355         /* now move the left to the result if they are not the
8356         same */
8357         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8358                 AOP_SIZE(result) > 1) {
8359                 
8360                 size = AOP_SIZE(result);
8361                 offset=0;
8362                 while (size--) {
8363                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8364                         if (*l == '@' && IS_AOP_PREG(result)) {
8365                                 
8366                                 pic14_emitcode("mov","a,%s",l);
8367                                 aopPut(AOP(result),"a",offset);
8368                         } else
8369                                 aopPut(AOP(result),l,offset);
8370                         offset++;
8371                 }
8372         }
8373         
8374         tlbl = newiTempLabel(NULL);
8375         tlbl1= newiTempLabel(NULL);
8376         size = AOP_SIZE(result);
8377         offset = size - 1;
8378         
8379         /* if it is only one byte then */
8380         if (size == 1) {
8381                 
8382                 tlbl = newiTempLabel(NULL);
8383                 if (!pic14_sameRegs(AOP(left),AOP(result))) {
8384                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
8385                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
8386                 }
8387                 
8388                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
8389                 emitpcode(POC_RLF,    popGet(AOP(result),0));
8390                 emitpLabel(tlbl->key);
8391                 emitpcode(POC_RRF,    popGet(AOP(result),0));
8392                 emitpcode(POC_ADDLW,  popGetLit(1));
8393                 emitSKPC;
8394                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8395                 
8396                 goto release ;
8397         }
8398         
8399         reAdjustPreg(AOP(result));
8400         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8401         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8402         CLRC;
8403         while (size--) {
8404                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8405                 MOVA(l);
8406                 pic14_emitcode("rrc","a");         
8407                 aopPut(AOP(result),"a",offset--);
8408         }
8409         reAdjustPreg(AOP(result));
8410         
8411         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8412         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8413         
8414 release:
8415         freeAsmop(left,NULL,ic,TRUE);
8416         freeAsmop (right,NULL,ic,TRUE);
8417         freeAsmop(result,NULL,ic,TRUE);
8418 }
8419
8420 /*-----------------------------------------------------------------*/
8421 /* genUnpackBits - generates code for unpacking bits               */
8422 /*-----------------------------------------------------------------*/
8423 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
8424 {    
8425         int shCnt;
8426         int offset = 0;       /* result byte offset */
8427         int rsize;            /* result size */
8428         int rlen = 0;         /* remaining bitfield length */
8429         sym_link *etype;      /* bitfield type information */
8430         int blen;             /* bitfield length */
8431         int bstr;             /* bitfield starting bit within byte */
8432
8433         FENTRY;
8434         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8435         etype = getSpec(operandType(result));
8436         rsize = getSize (operandType (result));
8437         blen = SPEC_BLEN (etype);
8438         bstr = SPEC_BSTR (etype);
8439         
8440         /* single bit field case */
8441         if (blen == 1) {
8442                 if (ifx) { /* that is for an if statement */
8443                         pCodeOp *pcop;
8444                         resolvedIfx rIfx;
8445                         resolveIfx(&rIfx,ifx);
8446                         if (ptype == -1) /* direct */
8447                                 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8448                         else
8449                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8450                         emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8451                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8452                         ifx->generated=1;
8453                 } else {
8454                         pCodeOp *pcop;
8455                         int i;
8456                         assert (!pic14_sameRegs (AOP(result), AOP(left)));
8457                         for (i=0; i < AOP_SIZE(result); i++)
8458                                 emitpcode (POC_CLRF, popGet (AOP(result), i));
8459                         if (ptype == -1) /* direct */
8460                                 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8461                         else
8462                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8463                         emitpcode(POC_BTFSC,pcop);
8464                         emitpcode(POC_BSF,newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),0,0));
8465                 }
8466                 return;
8467         }
8468
8469         {
8470           static int has_warned=0;
8471           if (!has_warned)
8472           {
8473             fprintf (stderr, "%s: bitfields with more than 1 bit are probably broken...", __FUNCTION__);
8474             has_warned=1;
8475           }
8476         }
8477
8478         /* read the first byte  */
8479         switch (ptype) {
8480                 
8481         case POINTER:
8482         case IPOINTER:
8483 //              pic14_emitcode("mov","a,@%s",rname);
8484                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8485                 break;
8486                 
8487         case PPOINTER:
8488                 pic14_emitcode("movx","a,@%s",rname);
8489                 break;
8490                 
8491         case FPOINTER:
8492                 pic14_emitcode("movx","a,@dptr");
8493                 break;
8494                 
8495         case CPOINTER:
8496                 pic14_emitcode("clr","a");
8497                 pic14_emitcode("movc","a","@a+dptr");
8498                 break;
8499                 
8500         case GPOINTER:
8501                 pic14_emitcode("lcall","__gptrget");
8502                 break;
8503         }
8504
8505         /* if we have bitdisplacement then it fits   */
8506         /* into this byte completely or if length is */
8507         /* less than a byte                          */
8508         if ((shCnt = SPEC_BSTR(etype)) || blen <= 8)  {
8509                 
8510                 /* shift right acc */
8511                 AccRsh(left,0,shCnt);
8512                 
8513                 pic14_emitcode("anl","a,#0x%02x",
8514                         ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8515                 aopPut(AOP(result),"a",offset);
8516                 return ;
8517         }
8518         
8519         /* bit field did not fit in a byte  */
8520         rlen = SPEC_BLEN(etype) - 8;
8521         aopPut(AOP(result),"a",offset++);
8522         
8523         while (1)  {
8524                 
8525                 switch (ptype) {
8526                 case POINTER:
8527                 case IPOINTER:
8528                         pic14_emitcode("inc","%s",rname);
8529                         pic14_emitcode("mov","a,@%s",rname);
8530                         break;
8531                         
8532                 case PPOINTER:
8533                         pic14_emitcode("inc","%s",rname);
8534                         pic14_emitcode("movx","a,@%s",rname);
8535                         break;
8536                         
8537                 case FPOINTER:
8538                         pic14_emitcode("inc","dptr");
8539                         pic14_emitcode("movx","a,@dptr");
8540                         break;
8541                         
8542                 case CPOINTER:
8543                         pic14_emitcode("clr","a");
8544                         pic14_emitcode("inc","dptr");
8545                         pic14_emitcode("movc","a","@a+dptr");
8546                         break;
8547                         
8548                 case GPOINTER:
8549                         pic14_emitcode("inc","dptr");
8550                         pic14_emitcode("lcall","__gptrget");
8551                         break;
8552                 }
8553                 
8554                 rlen -= 8;            
8555                 /* if we are done */
8556                 if ( rlen <= 0 )
8557                         break ;
8558                 
8559                 aopPut(AOP(result),"a",offset++);
8560                 
8561         }
8562         
8563         if (rlen) {
8564                 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8565                 aopPut(AOP(result),"a",offset);        
8566         }
8567         
8568         return ;
8569 }
8570
8571 #if 1
8572 /*-----------------------------------------------------------------*/
8573 /* genDataPointerGet - generates code when ptr offset is known     */
8574 /*-----------------------------------------------------------------*/
8575 static void genDataPointerGet (operand *left, 
8576         operand *result, 
8577         iCode *ic)
8578 {
8579         int size , offset = 0;
8580                 
8581         FENTRY;
8582         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8583         
8584         
8585         /* optimization - most of the time, left and result are the same
8586         * address, but different types. for the pic code, we could omit
8587         * the following
8588         */
8589         aopOp(result,ic,TRUE);
8590         
8591         if (pic14_sameRegs (AOP(left), AOP(result)))
8592                 return;
8593         
8594         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8595         
8596         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8597         
8598         size = AOP_SIZE(result);
8599         if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
8600         
8601         while (size--) {
8602                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8603                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8604                 offset++;
8605         }
8606         
8607         freeAsmop(left,NULL,ic,TRUE);
8608         freeAsmop(result,NULL,ic,TRUE);
8609 }
8610 #endif
8611 /*-----------------------------------------------------------------*/
8612 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8613 /*-----------------------------------------------------------------*/
8614 static void genNearPointerGet (operand *left, 
8615                                                            operand *result, 
8616                                                            iCode *ic)
8617 {
8618         asmop *aop = NULL;
8619         sym_link *ltype = operandType(left);
8620         sym_link *rtype = operandType(result);
8621         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8622         int direct = 0;
8623
8624         FENTRY;
8625         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8626         
8627         
8628         aopOp(left,ic,FALSE);
8629         
8630         /* if left is rematerialisable and
8631         result is not bit variable type and
8632         the left is pointer to data space i.e
8633         lower 128 bytes of space */
8634         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8635                 !IS_BITVAR(retype)         &&
8636                 DCL_TYPE(ltype) == POINTER) {
8637                 genDataPointerGet (left,result,ic);
8638                 return ;
8639         }
8640         
8641         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8642         aopOp (result,ic,FALSE);
8643         
8644         /* Check if can access directly instead of via a pointer */
8645         if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
8646                 direct = 1;
8647         }
8648
8649         /* If the pointer value is not in a the FSR then need to put it in */
8650         if (!AOP_INPREG(AOP(left)) && !direct) {
8651                 /* otherwise get a free pointer register */
8652                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8653                 if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */ 
8654                         emitpcode(POC_MOVLW, popGet(AOP(left),0));
8655                 else
8656                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
8657                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8658         }
8659         
8660         
8661 //      sym_link *etype;
8662         /* if bitfield then unpack the bits */
8663         if (IS_BITFIELD(retype)) 
8664                 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8665         else {
8666                 /* we have can just get the values */
8667                 int size = AOP_SIZE(result);
8668                 int offset = 0 ;  
8669                 
8670                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8671                 
8672                 while(size--) {
8673                         if (direct)
8674                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8675                         else
8676                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8677                         if (AOP_TYPE(result) == AOP_LIT) {
8678                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8679                         } else {
8680                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8681                         }
8682                         if (size && !direct)
8683                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8684                         offset++;
8685                 }
8686         }
8687         
8688         /* now some housekeeping stuff */
8689         if (aop) {
8690                 /* we had to allocate for this iCode */
8691                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8692                 freeAsmop(NULL,aop,ic,TRUE);
8693         } else { 
8694                 /* we did not allocate which means left
8695                 already in a pointer register, then
8696                 if size > 0 && this could be used again
8697                 we have to point it back to where it 
8698                 belongs */
8699                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8700                 if (AOP_SIZE(result) > 1 &&
8701                         !OP_SYMBOL(left)->remat &&
8702                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8703                         ic->depth )) {
8704                         int size = AOP_SIZE(result) - 1;
8705                         while (size--)
8706                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8707                 }
8708         }
8709         
8710         /* done */
8711         freeAsmop(left,NULL,ic,TRUE);
8712         freeAsmop(result,NULL,ic,TRUE);
8713
8714 }
8715
8716 /*-----------------------------------------------------------------*/
8717 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8718 /*-----------------------------------------------------------------*/
8719 static void genPagedPointerGet (operand *left, 
8720                                                                 operand *result, 
8721                                                                 iCode *ic)
8722 {
8723         asmop *aop = NULL;
8724         regs *preg = NULL ;
8725         char *rname ;
8726         sym_link *rtype, *retype;    
8727         
8728         FENTRY;
8729         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8730         
8731         rtype = operandType(result);
8732         retype= getSpec(rtype);
8733         
8734         aopOp(left,ic,FALSE);
8735         
8736         /* if the value is already in a pointer register
8737         then don't need anything more */
8738         if (!AOP_INPREG(AOP(left))) {
8739                 /* otherwise get a free pointer register */
8740                 aop = newAsmop(0);
8741                 preg = getFreePtr(ic,&aop,FALSE);
8742                 pic14_emitcode("mov","%s,%s",
8743                         preg->name,
8744                         aopGet(AOP(left),0,FALSE,TRUE));
8745                 rname = preg->name ;
8746         } else
8747                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8748         
8749         freeAsmop(left,NULL,ic,TRUE);
8750         aopOp (result,ic,FALSE);
8751         
8752         /* if bitfield then unpack the bits */
8753         if (IS_BITFIELD(retype)) 
8754                 genUnpackBits (result,left,rname,PPOINTER,0);
8755         else {
8756                 /* we have can just get the values */
8757                 int size = AOP_SIZE(result);
8758                 int offset = 0 ;  
8759                 
8760                 while (size--) {
8761                         
8762                         pic14_emitcode("movx","a,@%s",rname);
8763                         aopPut(AOP(result),"a",offset);
8764                         
8765                         offset++ ;
8766                         
8767                         if (size)
8768                                 pic14_emitcode("inc","%s",rname);
8769                 }
8770         }
8771         
8772         /* now some housekeeping stuff */
8773         if (aop) {
8774                 /* we had to allocate for this iCode */
8775                 freeAsmop(NULL,aop,ic,TRUE);
8776         } else { 
8777         /* we did not allocate which means left
8778         already in a pointer register, then
8779         if size > 0 && this could be used again
8780         we have to point it back to where it 
8781                 belongs */
8782                 if (AOP_SIZE(result) > 1 &&
8783                         !OP_SYMBOL(left)->remat &&
8784                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8785                         ic->depth )) {
8786                         int size = AOP_SIZE(result) - 1;
8787                         while (size--)
8788                                 pic14_emitcode("dec","%s",rname);
8789                 }
8790         }
8791         
8792         /* done */
8793         freeAsmop(result,NULL,ic,TRUE);
8794         
8795         
8796 }
8797
8798 /*-----------------------------------------------------------------*/
8799 /* genFarPointerGet - gget value from far space                    */
8800 /*-----------------------------------------------------------------*/
8801 static void genFarPointerGet (operand *left,
8802                                                           operand *result, iCode *ic)
8803 {
8804         int size, offset ;
8805         sym_link *retype = getSpec(operandType(result));
8806         
8807         FENTRY;
8808         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8809         
8810         aopOp(left,ic,FALSE);
8811         
8812         /* if the operand is already in dptr 
8813         then we do nothing else we move the value to dptr */
8814         if (AOP_TYPE(left) != AOP_STR) {
8815                 /* if this is remateriazable */
8816                 if (AOP_TYPE(left) == AOP_IMMD)
8817                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8818                 else { /* we need to get it byte by byte */
8819                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8820                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8821                         if (options.model == MODEL_FLAT24)
8822                         {
8823                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8824                         }
8825                 }
8826         }
8827         /* so dptr know contains the address */
8828         freeAsmop(left,NULL,ic,TRUE);
8829         aopOp(result,ic,FALSE);
8830         
8831         /* if bit then unpack */
8832         if (IS_BITFIELD(retype)) 
8833                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8834         else {
8835                 size = AOP_SIZE(result);
8836                 offset = 0 ;
8837                 
8838                 while (size--) {
8839                         pic14_emitcode("movx","a,@dptr");
8840                         aopPut(AOP(result),"a",offset++);
8841                         if (size)
8842                                 pic14_emitcode("inc","dptr");
8843                 }
8844         }
8845         
8846         freeAsmop(result,NULL,ic,TRUE);
8847 }
8848 #if 0
8849 /*-----------------------------------------------------------------*/
8850 /* genCodePointerGet - get value from code space                  */
8851 /*-----------------------------------------------------------------*/
8852 static void genCodePointerGet (operand *left,
8853                                                            operand *result, iCode *ic)
8854 {
8855         int size, offset ;
8856         sym_link *retype = getSpec(operandType(result));
8857         
8858         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8859         
8860         aopOp(left,ic,FALSE);
8861         
8862         /* if the operand is already in dptr 
8863         then we do nothing else we move the value to dptr */
8864         if (AOP_TYPE(left) != AOP_STR) {
8865                 /* if this is remateriazable */
8866                 if (AOP_TYPE(left) == AOP_IMMD)
8867                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8868                 else { /* we need to get it byte by byte */
8869                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8870                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8871                         if (options.model == MODEL_FLAT24)
8872                         {
8873                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8874                         }
8875                 }
8876         }
8877         /* so dptr know contains the address */
8878         freeAsmop(left,NULL,ic,TRUE);
8879         aopOp(result,ic,FALSE);
8880         
8881         /* if bit then unpack */
8882         if (IS_BITFIELD(retype)) 
8883                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8884         else {
8885                 size = AOP_SIZE(result);
8886                 offset = 0 ;
8887                 
8888                 while (size--) {
8889                         pic14_emitcode("clr","a");
8890                         pic14_emitcode("movc","a,@a+dptr");
8891                         aopPut(AOP(result),"a",offset++);
8892                         if (size)
8893                                 pic14_emitcode("inc","dptr");
8894                 }
8895         }
8896         
8897         freeAsmop(result,NULL,ic,TRUE);
8898 }
8899 #endif
8900 /*-----------------------------------------------------------------*/
8901 /* genGenPointerGet - gget value from generic pointer space        */
8902 /*-----------------------------------------------------------------*/
8903 static void genGenPointerGet (operand *left,
8904                                                           operand *result, iCode *ic)
8905 {
8906         int size, offset ;
8907         sym_link *retype = getSpec(operandType(result));
8908         
8909         FENTRY;
8910         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8911         aopOp(left,ic,FALSE);
8912         aopOp(result,ic,FALSE);
8913         
8914         
8915         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8916         
8917         /* if the operand is already in dptr 
8918         then we do nothing else we move the value to dptr */
8919         //  if (AOP_TYPE(left) != AOP_STR) {
8920         /* if this is remateriazable */
8921         if (AOP_TYPE(left) == AOP_IMMD) {
8922                 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8923                 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8924         }
8925         else { /* we need to get it byte by byte */
8926                 
8927                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8928                 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8929                 
8930                 size = AOP_SIZE(result);
8931                 offset = 0 ;
8932                 
8933                 while(size--) {
8934                         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8935                         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8936                         if(size)
8937                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8938                 }
8939                 goto release;
8940         }
8941         //}
8942         /* so dptr know contains the address */
8943         
8944         /* if bit then unpack */
8945         //if (IS_BITFIELD(retype)) 
8946         //  genUnpackBits(result,"dptr",GPOINTER);
8947         
8948 release:
8949         freeAsmop(left,NULL,ic,TRUE);
8950         freeAsmop(result,NULL,ic,TRUE);
8951         
8952 }
8953
8954 /*-----------------------------------------------------------------*/
8955 /* genConstPointerGet - get value from const generic pointer space */
8956 /*-----------------------------------------------------------------*/
8957 static void genConstPointerGet (operand *left,
8958                                                                 operand *result, iCode *ic)
8959 {
8960         //sym_link *retype = getSpec(operandType(result));
8961         symbol *albl, *blbl;//, *clbl;
8962         PIC_OPCODE poc;
8963         int i, size, lit;
8964         pCodeOp *pcop;
8965         
8966         FENTRY;
8967         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8968         aopOp(left,ic,FALSE);
8969         aopOp(result,ic,FALSE);
8970         
8971         size = AOP_SIZE(result);
8972         
8973         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8974         
8975         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8976
8977         lit = aop_isLitLike (AOP(left));
8978         poc = lit ? POC_MOVLW : POC_MOVFW;
8979
8980         if (lit)
8981         {
8982                 for (i = 0; i < size; i++)
8983                 {
8984                         albl = newiTempLabel(NULL);
8985                         blbl = newiTempLabel(NULL);
8986                         
8987                         emitpcode(POC_CALL,popGetLabel(albl->key));
8988                         pcop = popGetLabel(blbl->key);
8989                         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8990                         emitpcode(POC_GOTO,pcop);
8991                         
8992                         emitpLabel(albl->key);
8993                         emitpcode(poc,popGetAddr(AOP(left),1,i));
8994                         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8995                         emitpcode(poc,popGetAddr(AOP(left),0,i));
8996                         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8997                 
8998                         emitpLabel(blbl->key);
8999                         emitpcode(POC_MOVWF,popGet(AOP(result),i));
9000                 } // for
9001         } else {
9002                 albl = newiTempLabel(NULL);
9003                 blbl = newiTempLabel(NULL);
9004                 //clbl = newiTempLabel(NULL);
9005
9006                 emitpcode (POC_GOTO, popGetLabel (blbl->key));
9007                 
9008                 emitpLabel(albl->key);
9009                 emitpcode(poc,popGet(AOP(left),1));
9010                 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
9011                 emitpcode(poc,popGet(AOP(left),0));
9012                 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
9013                 
9014                 emitpLabel(blbl->key);
9015                 
9016                 for (i = 0; i < size; i++)
9017                 {
9018                         emitpcode(POC_CALL,popGetLabel(albl->key));
9019                         /* the next two instructions (plus clbl) might be useless... */
9020                         //pcop = popGetLabel(clbl->key);
9021                         //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
9022                         //emitpcode(POC_GOTO,pcop);
9023                         //emitpLabel(clbl->key);
9024
9025                         if (i+1 < size) {
9026                                 emitpcode (POC_INCF, popGet (AOP(left), 0));
9027                                 emitSKPNZ;
9028                                 emitpcode (POC_INCF, popGet (AOP(left), 1));
9029                         }
9030                         emitpcode(POC_MOVWF,popGet(AOP(result),i));
9031                 } // for
9032                 if (size > 1) {
9033                         /* restore left's value */
9034                         emitpcode (POC_MOVLW, popGetLit (size-1));
9035                         emitpcode (POC_SUBWF, popGet (AOP(left), 0));
9036                         emitSKPC;
9037                         emitpcode (POC_DECF, popGet (AOP(left), 1));
9038                 } // if
9039         } // if (lit)
9040         
9041         freeAsmop(left,NULL,ic,TRUE);
9042         freeAsmop(result,NULL,ic,TRUE);
9043         
9044 }
9045 /*-----------------------------------------------------------------*/
9046 /* genPointerGet - generate code for pointer get                   */
9047 /*-----------------------------------------------------------------*/
9048 static void genPointerGet (iCode *ic)
9049 {
9050         operand *left, *result ;
9051         sym_link *type, *etype;
9052         int p_type = -1;
9053         
9054         FENTRY;
9055         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9056         
9057         left = IC_LEFT(ic);
9058         result = IC_RESULT(ic) ;
9059         
9060         /* depending on the type of pointer we need to
9061         move it to the correct pointer register */
9062         type = operandType(left);
9063         etype = getSpec(type);
9064         
9065         if (IS_PTR_CONST(type))
9066                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9067         
9068         /* if left is of type of pointer then it is simple */
9069         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9070                 p_type = DCL_TYPE(type);
9071         else {
9072                 /* we have to go by the storage class */
9073                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9074                 
9075                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9076                 
9077                 if (SPEC_OCLS(etype)->codesp ) {
9078                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9079                         //p_type = CPOINTER ; 
9080                 }
9081                 else
9082                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9083                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9084                         /*p_type = FPOINTER ;*/ 
9085                         else
9086                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9087                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9088                                 /*        p_type = PPOINTER; */
9089                                 else
9090                                         if (SPEC_OCLS(etype) == idata )
9091                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9092                                         /*      p_type = IPOINTER; */
9093                                         else
9094                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9095                                         /*      p_type = POINTER ; */
9096         }
9097         
9098         /* now that we have the pointer type we assign
9099         the pointer values */
9100         switch (p_type) {
9101                 
9102         case POINTER: 
9103         case IPOINTER:
9104                 genNearPointerGet (left,result,ic);
9105                 break;
9106                 
9107         case PPOINTER:
9108                 genPagedPointerGet(left,result,ic);
9109                 break;
9110                 
9111         case FPOINTER:
9112                 genFarPointerGet (left,result,ic);
9113                 break;
9114                 
9115         case CPOINTER:
9116                 genConstPointerGet (left,result,ic);
9117                 //pic14_emitcodePointerGet (left,result,ic);
9118                 break;
9119                 
9120         case GPOINTER:
9121                 if (IS_CODEPTR(type) || IS_PTR_CONST(type) || SPEC_CONST(etype))
9122                         genConstPointerGet (left,result,ic);
9123                 else
9124                         genGenPointerGet (left,result,ic);
9125                 break;
9126         default:
9127                 assert ( !"unhandled pointer type" );
9128                 break;
9129         }
9130         
9131 }
9132
9133 /*-----------------------------------------------------------------*/
9134 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into  */
9135 /* A through a pointer register (R0, R1, or DPTR). The original    */
9136 /* value of A can be preserved in B.                               */
9137 /* PIC has to use INDF register.                                   */
9138 /*-----------------------------------------------------------------*/
9139 static void
9140 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9141 {
9142     FENTRY;
9143     switch (p_type)
9144     {
9145     case IPOINTER:
9146     case POINTER:
9147                 if (preserveAinB)
9148                         pic14_emitcode ("mov", "b,a");
9149 //              pic14_emitcode ("mov", "a,@%s", rname);
9150                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
9151                 break;
9152                 
9153     case PPOINTER:
9154                 if (preserveAinB)
9155                         pic14_emitcode ("mov", "b,a");
9156                 pic14_emitcode ("movx", "a,@%s", rname);
9157                 break;
9158                 
9159     case FPOINTER:
9160                 if (preserveAinB)
9161                         pic14_emitcode ("mov", "b,a");
9162                 pic14_emitcode ("movx", "a,@dptr");
9163                 break;
9164                 
9165     case CPOINTER:
9166                 if (preserveAinB)
9167                         pic14_emitcode ("mov", "b,a");
9168                 pic14_emitcode ("clr", "a");
9169                 pic14_emitcode ("movc", "a,@a+dptr");
9170                 break;
9171                 
9172     case GPOINTER:
9173                 if (preserveAinB)
9174         {
9175                         pic14_emitcode ("push", "b");
9176                         pic14_emitcode ("push", "acc");
9177         }
9178                 pic14_emitcode ("lcall", "__gptrget");
9179                 if (preserveAinB)
9180                         pic14_emitcode ("pop", "b");
9181                 break;
9182     }
9183 }
9184
9185 /*-----------------------------------------------------------------*/
9186 /* emitPtrByteSet - emits code to set a byte from src through a    */
9187 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
9188 /*-----------------------------------------------------------------*/
9189 static void
9190 emitPtrByteSet (char *rname, int p_type, char *src)
9191 {
9192     FENTRY;
9193     switch (p_type)
9194     {
9195     case IPOINTER:
9196     case POINTER:
9197                 if (*src=='@')
9198         {
9199                         MOVA (src);
9200                         pic14_emitcode ("mov", "@%s,a", rname);
9201         }
9202                 else
9203 //                      pic14_emitcode ("mov", "@%s,%s", rname, src);
9204                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9205                 break;
9206                 
9207     case PPOINTER:
9208                 MOVA (src);
9209                 pic14_emitcode ("movx", "@%s,a", rname);
9210                 break;
9211                 
9212     case FPOINTER:
9213                 MOVA (src);
9214                 pic14_emitcode ("movx", "@dptr,a");
9215                 break;
9216                 
9217     case GPOINTER:
9218                 MOVA (src);
9219                 pic14_emitcode ("lcall", "__gptrput");
9220                 break;
9221     }
9222 }
9223
9224 /*-----------------------------------------------------------------*/
9225 /* genPackBits - generates code for packed bit storage             */
9226 /*-----------------------------------------------------------------*/
9227 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
9228 {
9229         int offset = 0;       /* source byte offset */
9230         int rlen = 0;         /* remaining bitfield length */
9231         int blen;             /* bitfield length */
9232         int bstr;             /* bitfield starting bit within byte */
9233         int litval;           /* source literal value (if AOP_LIT) */
9234         unsigned char mask;   /* bitmask within current byte */
9235
9236         FENTRY;
9237         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9238         
9239         blen = SPEC_BLEN (etype);
9240         bstr = SPEC_BSTR (etype);
9241         
9242         /* If the bitfield length is less than a byte */
9243         if (blen < 8)
9244     {
9245                 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9246                         (unsigned char) (0xFF >> (8 - bstr)));
9247                 
9248                 if (AOP_TYPE (right) == AOP_LIT)
9249         {
9250                         /* Case with a bitfield length <8 and literal source
9251                         */
9252                         int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9253                         if (blen == 1) {
9254                                 if (p_type == -1) {
9255                                         pCodeOp *pcop;
9256                                         if (AOP(result)->type == AOP_PCODE)
9257                                                 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9258                                         else
9259                                                 pcop = popGet(AOP(result),0);
9260                                         emitpcode(lit?POC_BSF:POC_BCF,pcop);
9261                                 } else {
9262                                         emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
9263                                 }
9264                                 return;
9265                         } else {
9266                                 litval = lit << bstr;
9267                                 litval &= (~mask) & 0xff;
9268                                 if (p_type == -1)
9269                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9270                                 else
9271                                         emitPtrByteGet (rname, p_type, FALSE);
9272                                 if ((mask|litval)!=0xff)
9273                                         emitpcode(POC_ANDLW,popGetLit(mask));
9274                                 if (litval)
9275                                         emitpcode(POC_IORLW,popGetLit(litval));
9276                         }
9277         }
9278                 else
9279         {
9280                         if (blen==1) {
9281                                 if (p_type == -1) {
9282                                         /* 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 */
9283                                         emitpcode(POC_RRFW,popGet(AOP(right),0));
9284                                         emitSKPC;
9285                                         emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9286                                         emitSKPNC;
9287                                         emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9288                                         return;
9289                                 } else if (p_type!=GPOINTER) {
9290                                         /* Case with a bitfield length == 1 and no generic pointer
9291                                         */
9292                                         if (AOP_TYPE (right) == AOP_CRY)
9293                                                 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9294                                         else
9295                                         {
9296                                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9297                                                 pic14_emitcode ("rrc","a");
9298                                         }
9299                                         emitPtrByteGet (rname, p_type, FALSE);
9300                                         pic14_emitcode ("mov","acc.%d,c",bstr);
9301                                 }
9302             }
9303                         else
9304             {
9305                                 //bool pushedB;
9306                                 /* Case with a bitfield length < 8 and arbitrary source
9307                                 */
9308                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9309                                 /* shift and mask source value */
9310                                 AccLsh (right,0,bstr);
9311                                 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9312                                 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
9313                                 
9314                                 //pushedB = pushB ();
9315                                 if (p_type == -1)
9316                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9317                                 else
9318                                         emitPtrByteGet (rname, p_type, TRUE);
9319                                 
9320                                 pic14_emitcode ("anl", "a,#0x%02x", mask);
9321                                 pic14_emitcode ("orl", "a,b");
9322                                 emitpcode(POC_ANDLW,popGetLit(mask));
9323                                 emitpcode(POC_IORFW,popGet(AOP(right),0));
9324                                 if (p_type == GPOINTER)
9325                                         pic14_emitcode ("pop", "b");
9326                                 
9327                                 //popB (pushedB);
9328                         }
9329         }
9330                 
9331                 if (p_type == -1)
9332                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9333                 else
9334                         emitPtrByteSet (rname, p_type, "a");
9335                 return;
9336     }
9337         
9338         /* Bit length is greater than 7 bits. In this case, copy  */
9339         /* all except the partial byte at the end                 */
9340         for (rlen=blen;rlen>=8;rlen-=8)
9341     {
9342                 emitPtrByteSet (rname, p_type,
9343                         aopGet (AOP (right), offset++, FALSE, TRUE) );
9344                 if (rlen>8)
9345                         pic14_emitcode ("inc", "%s", rname);
9346     }
9347         
9348         /* If there was a partial byte at the end */
9349         if (rlen)
9350     {
9351                 mask = (((unsigned char) -1 << rlen) & 0xff);
9352                 
9353                 if (AOP_TYPE (right) == AOP_LIT)
9354         {
9355                 /* Case with partial byte and literal source
9356                         */
9357                         litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9358                         litval >>= (blen-rlen);
9359                         litval &= (~mask) & 0xff;
9360                         emitPtrByteGet (rname, p_type, FALSE);
9361                         if ((mask|litval)!=0xff)
9362                                 pic14_emitcode ("anl","a,#0x%02x", mask);
9363                         if (litval)
9364                                 pic14_emitcode ("orl","a,#0x%02x", litval);
9365         }
9366                 else
9367         {
9368                         //bool pushedB;
9369                         /* Case with partial byte and arbitrary source
9370                         */
9371                         MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9372                         pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9373                         
9374                         //pushedB = pushB ();
9375                         /* transfer A to B and get next byte */
9376                         emitPtrByteGet (rname, p_type, TRUE);
9377                         
9378                         pic14_emitcode ("anl", "a,#0x%02x", mask);
9379                         pic14_emitcode ("orl", "a,b");
9380                         if (p_type == GPOINTER)
9381                                 pic14_emitcode ("pop", "b");
9382                         
9383                         //popB (pushedB);
9384         }
9385                 emitPtrByteSet (rname, p_type, "a");
9386     }
9387         
9388 }
9389
9390 /*-----------------------------------------------------------------*/
9391 /* SetIrp - Set IRP bit                                            */
9392 /*-----------------------------------------------------------------*/
9393 void SetIrp(operand *result) {
9394         FENTRY;
9395         if (AOP_TYPE(result) == AOP_LIT) {
9396                 unsigned lit = (unsigned)operandLitValue(result);
9397                 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9398         } else {
9399                 if (PCOP(AOP(result))->type == PO_LITERAL) {
9400                         int addrs = PCOL(AOP(result))->lit;
9401                         emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9402                 } else {
9403                         emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
9404                         if(AOP_SIZE(result) > 1) {
9405                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9406                                 emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9407                         }
9408                 }
9409         }
9410 }
9411
9412 /*-----------------------------------------------------------------*/
9413 /* genDataPointerSet - remat pointer to data space                 */
9414 /*-----------------------------------------------------------------*/
9415 static void genDataPointerSet(operand *right,
9416         operand *result,
9417         iCode *ic)
9418 {
9419         int size, offset = 0 ;
9420         
9421         FENTRY;
9422         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9423         aopOp(right,ic,FALSE);
9424         aopOp(result,ic,FALSE);
9425         
9426         size = AOP_SIZE(right);
9427         /*
9428         if ( AOP_TYPE(result) == AOP_PCODE) {
9429         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9430         AOP(result)->aopu.pcop->name,
9431         PCOI(AOP(result)->aopu.pcop)->offset);
9432         }
9433         */
9434         
9435         // tsd, was l+1 - the underline `_' prefix was being stripped
9436         while (size--) {
9437                 emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
9438                 
9439                 if (AOP_TYPE(right) == AOP_LIT) {
9440                         unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9441                         lit = lit >> (8*offset);
9442                         if(lit&0xff) {
9443                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9444                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9445                         } else {
9446                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9447                         }
9448                 } else {
9449                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9450                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9451                 }
9452                 
9453                 offset++;
9454         }
9455         
9456         freeAsmop(right,NULL,ic,TRUE);
9457         freeAsmop(result,NULL,ic,TRUE);
9458 }
9459
9460 /*-----------------------------------------------------------------*/
9461 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9462 /*-----------------------------------------------------------------*/
9463 static void genNearPointerSet (operand *right,
9464                                                            operand *result, 
9465                                                            iCode *ic)
9466 {
9467         asmop *aop = NULL;
9468         sym_link *ptype = operandType(result);
9469         sym_link *retype = getSpec(operandType(right));
9470         sym_link *letype = getSpec(ptype);
9471         int direct = 0;
9472         
9473         
9474         FENTRY;
9475         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9476         aopOp(result,ic,FALSE);
9477         
9478         
9479         /* if the result is rematerializable &
9480         in data space & not a bit variable */
9481         //if (AOP_TYPE(result) == AOP_IMMD &&
9482         if (AOP_TYPE(result) == AOP_PCODE &&
9483                 DCL_TYPE(ptype) == POINTER   &&
9484                 !IS_BITVAR (retype) &&
9485                 !IS_BITVAR (letype)) {
9486                 genDataPointerSet (right,result,ic);
9487                 freeAsmop(result,NULL,ic,TRUE);
9488                 return;
9489         }
9490
9491         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9492         aopOp(right,ic,FALSE);
9493         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9494         
9495         /* Check if can access directly instead of via a pointer */
9496         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9497                 direct = 1;
9498         }
9499
9500         /* If the pointer value is not in a the FSR then need to put it in */
9501         if (!AOP_INPREG(AOP(result)) && !direct) {
9502                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9503                 if (PCOP(AOP(result))->type == PO_LITERAL) 
9504                         emitpcode(POC_MOVLW, popGet(AOP(result),0));
9505                 else
9506                         emitpcode(POC_MOVFW, popGet(AOP(result),0));
9507                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
9508         }
9509
9510         /* Must set/reset IRP bit for use with FSR. */
9511         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9512         if (!direct)
9513                 SetIrp(result);
9514
9515         /* if bitfield then unpack the bits */
9516         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9517                 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
9518         } else {
9519                 /* we have can just get the values */
9520                 int size = AOP_SIZE(right);
9521                 int offset = 0 ;    
9522                 
9523                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9524                 while (size--) {
9525                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9526                         if (*l == '@' ) {
9527                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9528                         } else {
9529                                 if (AOP_TYPE(right) == AOP_LIT) {
9530                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9531                                 } else {
9532                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9533                                 }
9534                                 if (direct)
9535                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9536                                 else
9537                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9538                         }
9539                         if (size && !direct)
9540                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9541                         offset++;
9542                 }
9543         }
9544         
9545         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9546         /* now some housekeeping stuff */
9547         if (aop) {
9548                 /* we had to allocate for this iCode */
9549                 freeAsmop(NULL,aop,ic,TRUE);
9550         } else { 
9551                 /* we did not allocate which means left
9552                 already in a pointer register, then
9553                 if size > 0 && this could be used again
9554                 we have to point it back to where it 
9555                 belongs */
9556                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9557                 if (AOP_SIZE(right) > 1 &&
9558                         !OP_SYMBOL(result)->remat &&
9559                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9560                         ic->depth )) {
9561                         int size = AOP_SIZE(right) - 1;
9562                         while (size--)
9563                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9564                 }
9565         }
9566         
9567         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9568         /* done */
9569
9570         freeAsmop(right,NULL,ic,TRUE);
9571         freeAsmop(result,NULL,ic,TRUE);
9572 }
9573
9574 /*-----------------------------------------------------------------*/
9575 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9576 /*-----------------------------------------------------------------*/
9577 static void genPagedPointerSet (operand *right,
9578                                                                 operand *result, 
9579                                                                 iCode *ic)
9580 {
9581         asmop *aop = NULL;
9582         regs *preg = NULL ;
9583         char *rname , *l;
9584         sym_link *retype;
9585         
9586         FENTRY;
9587         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9588         
9589         retype= getSpec(operandType(right));
9590         
9591         aopOp(result,ic,FALSE);
9592         
9593         /* if the value is already in a pointer register
9594         then don't need anything more */
9595         if (!AOP_INPREG(AOP(result))) {
9596                 /* otherwise get a free pointer register */
9597                 aop = newAsmop(0);
9598                 preg = getFreePtr(ic,&aop,FALSE);
9599                 pic14_emitcode("mov","%s,%s",
9600                         preg->name,
9601                         aopGet(AOP(result),0,FALSE,TRUE));
9602                 rname = preg->name ;
9603         } else
9604                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9605         
9606         freeAsmop(result,NULL,ic,TRUE);
9607         aopOp (right,ic,FALSE);
9608         
9609         /* if bitfield then unpack the bits */
9610         if (IS_BITFIELD(retype)) 
9611                 genPackBits (retype,result,right,rname,PPOINTER);
9612         else {
9613                 /* we have can just get the values */
9614                 int size = AOP_SIZE(right);
9615                 int offset = 0 ;  
9616                 
9617                 while (size--) {
9618                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9619                         
9620                         MOVA(l);
9621                         pic14_emitcode("movx","@%s,a",rname);
9622                         
9623                         if (size)
9624                                 pic14_emitcode("inc","%s",rname);
9625                         
9626                         offset++;
9627                 }
9628         }
9629         
9630         /* now some housekeeping stuff */
9631         if (aop) {
9632                 /* we had to allocate for this iCode */
9633                 freeAsmop(NULL,aop,ic,TRUE);
9634         } else { 
9635         /* we did not allocate which means left
9636         already in a pointer register, then
9637         if size > 0 && this could be used again
9638         we have to point it back to where it 
9639                 belongs */
9640                 if (AOP_SIZE(right) > 1 &&
9641                         !OP_SYMBOL(result)->remat &&
9642                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9643                         ic->depth )) {
9644                         int size = AOP_SIZE(right) - 1;
9645                         while (size--)
9646                                 pic14_emitcode("dec","%s",rname);
9647                 }
9648         }
9649         
9650         /* done */
9651         freeAsmop(right,NULL,ic,TRUE);
9652         
9653         
9654 }
9655
9656 /*-----------------------------------------------------------------*/
9657 /* genFarPointerSet - set value from far space                     */
9658 /*-----------------------------------------------------------------*/
9659 static void genFarPointerSet (operand *right,
9660                                                           operand *result, iCode *ic)
9661 {
9662         int size, offset ;
9663         sym_link *retype = getSpec(operandType(right));
9664         
9665         FENTRY;
9666         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9667         aopOp(result,ic,FALSE);
9668         
9669         /* if the operand is already in dptr 
9670         then we do nothing else we move the value to dptr */
9671         if (AOP_TYPE(result) != AOP_STR) {
9672                 /* if this is remateriazable */
9673                 if (AOP_TYPE(result) == AOP_IMMD)
9674                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9675                 else { /* we need to get it byte by byte */
9676                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9677                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9678                         if (options.model == MODEL_FLAT24)
9679                         {
9680                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9681                         }
9682                 }
9683         }
9684         /* so dptr know contains the address */
9685         freeAsmop(result,NULL,ic,TRUE);
9686         aopOp(right,ic,FALSE);
9687         
9688         /* if bit then unpack */
9689         if (IS_BITFIELD(retype)) 
9690                 genPackBits(retype,result,right,"dptr",FPOINTER);
9691         else {
9692                 size = AOP_SIZE(right);
9693                 offset = 0 ;
9694                 
9695                 while (size--) {
9696                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9697                         MOVA(l);
9698                         pic14_emitcode("movx","@dptr,a");
9699                         if (size)
9700                                 pic14_emitcode("inc","dptr");
9701                 }
9702         }
9703         
9704         freeAsmop(right,NULL,ic,TRUE);
9705 }
9706
9707 /*-----------------------------------------------------------------*/
9708 /* genGenPointerSet - set value from generic pointer space         */
9709 /*-----------------------------------------------------------------*/
9710 static void genGenPointerSet (operand *right,
9711                                                           operand *result, iCode *ic)
9712 {
9713         sym_link *ptype = operandType(result);
9714         sym_link *retype = getSpec(operandType(right));
9715         sym_link *letype = getSpec (ptype);
9716         
9717         FENTRY;
9718         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9719         
9720         aopOp(result,ic,FALSE);
9721         aopOp(right,ic,FALSE);
9722         
9723         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9724         
9725         /* if the operand is already in dptr 
9726         then we do nothing else we move the value to dptr */
9727         if (AOP_TYPE(result) != AOP_STR) {
9728                 /* if this is remateriazable */
9729                 if (AOP_TYPE(result) == AOP_IMMD) {
9730                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9731                         pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9732                 }
9733                 else {
9734                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9735                         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9736
9737                         /* Must set/reset IRP bit for use with FSR. */
9738                         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9739                         SetIrp(result);
9740                 }
9741         }
9742
9743         /* if bitfield then unpack the bits */
9744         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9745                 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9746         } else {
9747                 /* we have can just get the values */
9748                 int size = AOP_SIZE(right);
9749                 int offset = 0 ;    
9750                 
9751                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9752                 while (size--) {
9753                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9754                         if (*l == '@' ) {
9755                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9756                         } else {
9757                                 if (AOP_TYPE(right) == AOP_LIT) {
9758                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9759                                 } else {
9760                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9761                                 }
9762                                 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9763                         }
9764                         if (size)
9765                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9766                         offset++;
9767                 }
9768         }
9769         
9770         freeAsmop(right,NULL,ic,TRUE);
9771         freeAsmop(result,NULL,ic,TRUE);
9772 }
9773
9774 /*-----------------------------------------------------------------*/
9775 /* genPointerSet - stores the value into a pointer location        */
9776 /*-----------------------------------------------------------------*/
9777 static void genPointerSet (iCode *ic)
9778 {    
9779         operand *right, *result ;
9780         sym_link *type, *etype;
9781         int p_type;
9782         
9783         FENTRY;
9784         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9785         
9786         right = IC_RIGHT(ic);
9787         result = IC_RESULT(ic) ;
9788         
9789         /* depending on the type of pointer we need to
9790         move it to the correct pointer register */
9791         type = operandType(result);
9792         etype = getSpec(type);
9793         /* if left is of type of pointer then it is simple */
9794         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9795                 p_type = DCL_TYPE(type);
9796         }
9797         else {
9798                 /* we have to go by the storage class */
9799                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9800                 
9801                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9802                 /*      p_type = CPOINTER ;  */
9803                 /*  } */
9804                 /*  else */
9805                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9806                 /*    p_type = FPOINTER ; */
9807                 /*      else */
9808                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9809                 /*        p_type = PPOINTER ; */
9810                 /*    else */
9811                 /*        if (SPEC_OCLS(etype) == idata ) */
9812                 /*      p_type = IPOINTER ; */
9813                 /*        else */
9814                 /*      p_type = POINTER ; */
9815         }
9816         
9817         /* now that we have the pointer type we assign
9818         the pointer values */
9819         switch (p_type) {
9820                 
9821         case POINTER:
9822         case IPOINTER:
9823                 genNearPointerSet (right,result,ic);
9824                 break;
9825                 
9826         case PPOINTER:
9827                 genPagedPointerSet (right,result,ic);
9828                 break;
9829                 
9830         case FPOINTER:
9831                 genFarPointerSet (right,result,ic);
9832                 break;
9833                 
9834         case GPOINTER:
9835                 genGenPointerSet (right,result,ic);
9836                 break;
9837                 
9838         default:
9839                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9840                         "genPointerSet: illegal pointer type");
9841         }
9842 }
9843
9844 /*-----------------------------------------------------------------*/
9845 /* genIfx - generate code for Ifx statement                        */
9846 /*-----------------------------------------------------------------*/
9847 static void genIfx (iCode *ic, iCode *popIc)
9848 {
9849         operand *cond = IC_COND(ic);
9850         int isbit =0;
9851         
9852         FENTRY;
9853         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9854         
9855         aopOp(cond,ic,FALSE);
9856         
9857         /* get the value into acc */
9858         if (AOP_TYPE(cond) != AOP_CRY)
9859                 pic14_toBoolean(cond);
9860         else
9861                 isbit = 1;
9862         /* the result is now in the accumulator */
9863         freeAsmop(cond,NULL,ic,TRUE);
9864         
9865         /* if there was something to be popped then do it */
9866         if (popIc)
9867                 genIpop(popIc);
9868         
9869         /* if the condition is  a bit variable */
9870         if (isbit && IS_ITEMP(cond) && 
9871                 SPIL_LOC(cond)) {
9872                 genIfxJump(ic,SPIL_LOC(cond)->rname);
9873                 DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9874         }
9875         else {
9876                 if (isbit && !IS_ITEMP(cond))
9877                         genIfxJump(ic,OP_SYMBOL(cond)->rname);
9878                 else
9879                         genIfxJump(ic,"a");
9880         }
9881         ic->generated = 1;
9882         
9883 }
9884
9885 /*-----------------------------------------------------------------*/
9886 /* genAddrOf - generates code for address of                       */
9887 /*-----------------------------------------------------------------*/
9888 static void genAddrOf (iCode *ic)
9889 {
9890         operand *right, *result, *left;
9891         int size, offset ;
9892         
9893         FENTRY;
9894         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9895         
9896         
9897         //aopOp(IC_RESULT(ic),ic,FALSE);
9898         
9899         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9900         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9901         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9902         
9903         DEBUGpic14_AopType(__LINE__,left,right,result);
9904         assert (IS_SYMOP (left));
9905         
9906         /* sanity check: generic pointers to code space are not yet supported,
9907          * pionters to codespace must not be assigned addresses of __data values. */
9908  #if 0
9909         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9910         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)));
9911         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)));
9912         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)));
9913         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)));
9914 #endif
9915
9916         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9917           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9918                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9919                 OP_SYMBOL(left)->name);
9920         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9921           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9922                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9923                 OP_SYMBOL(left)->name);
9924         }
9925         
9926         size = AOP_SIZE(IC_RESULT(ic));
9927         offset = 0;
9928         
9929         while (size--) {
9930                 /* fixing bug #863624, reported from (errolv) */
9931                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9932                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9933                 
9934 #if 0
9935                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9936                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9937 #endif
9938                 offset++;
9939         }
9940         
9941         freeAsmop(left,NULL,ic,FALSE);
9942         freeAsmop(result,NULL,ic,TRUE);
9943         
9944 }
9945
9946 #if 0
9947 /*-----------------------------------------------------------------*/
9948 /* genFarFarAssign - assignment when both are in far space         */
9949 /*-----------------------------------------------------------------*/
9950 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9951 {
9952         int size = AOP_SIZE(right);
9953         int offset = 0;
9954         char *l ;
9955         /* first push the right side on to the stack */
9956         while (size--) {
9957                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9958                 MOVA(l);
9959                 pic14_emitcode ("push","acc");
9960         }
9961         
9962         freeAsmop(right,NULL,ic,FALSE);
9963         /* now assign DPTR to result */
9964         aopOp(result,ic,FALSE);
9965         size = AOP_SIZE(result);
9966         while (size--) {
9967                 pic14_emitcode ("pop","acc");
9968                 aopPut(AOP(result),"a",--offset);
9969         }
9970         freeAsmop(result,NULL,ic,FALSE);
9971         
9972 }
9973 #endif
9974
9975 /*-----------------------------------------------------------------*/
9976 /* genAssign - generate code for assignment                        */
9977 /*-----------------------------------------------------------------*/
9978 static void genAssign (iCode *ic)
9979 {
9980         operand *result, *right;
9981         int size, offset,know_W;
9982         unsigned long lit = 0L;
9983         
9984         result = IC_RESULT(ic);
9985         right  = IC_RIGHT(ic) ;
9986         
9987         FENTRY;
9988         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9989         
9990         /* if they are the same */
9991         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9992                 return ;
9993         
9994         aopOp(right,ic,FALSE);
9995         aopOp(result,ic,TRUE);
9996         
9997         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9998         
9999         /* if they are the same registers */
10000         if (pic14_sameRegs(AOP(right),AOP(result)))
10001                 goto release;
10002
10003         /* special case: assign from __code */
10004         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10005                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10006                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10007                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10008                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10009         {
10010           emitpComment ("genAssign from CODESPACE");
10011           genConstPointerGet (right, result, ic);
10012           goto release;
10013         }
10014         
10015         /* just for symmetry reasons... */
10016         if (!IS_ITEMP(result)
10017                 && IS_SYMOP (result)
10018                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10019         {
10020           assert ( !"cannot write to CODESPACE" );
10021         }
10022
10023         /* if the result is a bit */
10024         if (AOP_TYPE(result) == AOP_CRY) {
10025                 
10026         /* if the right size is a literal then
10027                 we know what the value is */
10028                 if (AOP_TYPE(right) == AOP_LIT) {
10029                         
10030                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10031                                 popGet(AOP(result),0));
10032                         
10033                         if (((int) operandLitValue(right))) 
10034                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10035                                 AOP(result)->aopu.aop_dir,
10036                                 AOP(result)->aopu.aop_dir);
10037                         else
10038                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10039                                 AOP(result)->aopu.aop_dir,
10040                                 AOP(result)->aopu.aop_dir);
10041                         goto release;
10042                 }
10043                 
10044                 /* the right is also a bit variable */
10045                 if (AOP_TYPE(right) == AOP_CRY) {
10046                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10047                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10048                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10049                         
10050                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10051                                 AOP(result)->aopu.aop_dir,
10052                                 AOP(result)->aopu.aop_dir);
10053                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10054                                 AOP(right)->aopu.aop_dir,
10055                                 AOP(right)->aopu.aop_dir);
10056                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10057                                 AOP(result)->aopu.aop_dir,
10058                                 AOP(result)->aopu.aop_dir);
10059                         goto release ;
10060                 }
10061                 
10062                 /* we need to or */
10063                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10064                 pic14_toBoolean(right);
10065                 emitSKPZ;
10066                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10067                 //aopPut(AOP(result),"a",0);
10068                 goto release ;
10069         }
10070         
10071         /* bit variables done */
10072         /* general case */
10073         size = AOP_SIZE(result);
10074         offset = 0 ;
10075         if(AOP_TYPE(right) == AOP_LIT)
10076                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10077         
10078         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10079                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10080                 if(aopIdx(AOP(result),0) == 4) {
10081                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10082                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10083                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10084                         goto release;
10085                 } else
10086                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10087         }
10088         
10089         know_W=-1;
10090         while (size--) {
10091                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10092                 if(AOP_TYPE(right) == AOP_LIT) {
10093                         if(lit&0xff) {
10094                                 if(know_W != (int)(lit&0xff))
10095                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10096                                 know_W = lit&0xff;
10097                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10098                         } else
10099                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10100                         
10101                         lit >>= 8;
10102                         
10103                 } else if (AOP_TYPE(right) == AOP_CRY) {
10104                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10105                         if(offset == 0) {
10106                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10107                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10108                         }
10109                 } else {
10110                         mov2w (AOP(right), offset);
10111                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10112                 }
10113                 
10114                 offset++;
10115         }
10116         
10117         
10118 release:
10119         freeAsmop (right,NULL,ic,FALSE);
10120         freeAsmop (result,NULL,ic,TRUE);
10121 }   
10122
10123 /*-----------------------------------------------------------------*/
10124 /* genJumpTab - genrates code for jump table                       */
10125 /*-----------------------------------------------------------------*/
10126 static void genJumpTab (iCode *ic)
10127 {
10128         symbol *jtab;
10129         char *l;
10130         
10131         FENTRY;
10132         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10133         
10134         aopOp(IC_JTCOND(ic),ic,FALSE);
10135         /* get the condition into accumulator */
10136         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10137         MOVA(l);
10138         /* multiply by three */
10139         pic14_emitcode("add","a,acc");
10140         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10141         
10142         jtab = newiTempLabel(NULL);
10143         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10144         pic14_emitcode("jmp","@a+dptr");
10145         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10146         
10147         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10148         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10149         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10150         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10151         emitSKPNC;
10152         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10153         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10154         emitpLabel(jtab->key);
10155         
10156         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10157         
10158         /* now generate the jump labels */
10159         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10160         jtab = setNextItem(IC_JTLABELS(ic))) {
10161                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10162                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10163                 
10164         }
10165         
10166 }
10167
10168 /*-----------------------------------------------------------------*/
10169 /* genMixedOperation - gen code for operators between mixed types  */
10170 /*-----------------------------------------------------------------*/
10171 /*
10172 TSD - Written for the PIC port - but this unfortunately is buggy.
10173 This routine is good in that it is able to efficiently promote 
10174 types to different (larger) sizes. Unfortunately, the temporary
10175 variables that are optimized out by this routine are sometimes
10176 used in other places. So until I know how to really parse the 
10177 iCode tree, I'm going to not be using this routine :(.
10178 */
10179 static int genMixedOperation (iCode *ic)
10180 {
10181         FENTRY;
10182 #if 0
10183         operand *result = IC_RESULT(ic);
10184         sym_link *ctype = operandType(IC_LEFT(ic));
10185         operand *right = IC_RIGHT(ic);
10186         int ret = 0;
10187         int big,small;
10188         int offset;
10189         
10190         iCode *nextic;
10191         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10192         
10193         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10194         
10195         nextic = ic->next;
10196         if(!nextic)
10197                 return 0;
10198         
10199         nextright = IC_RIGHT(nextic);
10200         nextleft  = IC_LEFT(nextic);
10201         nextresult = IC_RESULT(nextic);
10202         
10203         aopOp(right,ic,FALSE);
10204         aopOp(result,ic,FALSE);
10205         aopOp(nextright,  nextic, FALSE);
10206         aopOp(nextleft,   nextic, FALSE);
10207         aopOp(nextresult, nextic, FALSE);
10208         
10209         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10210                 
10211                 operand *t = right;
10212                 right = nextright;
10213                 nextright = t; 
10214                 
10215                 pic14_emitcode(";remove right +","");
10216                 
10217         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10218         /*
10219         operand *t = right;
10220         right = nextleft;
10221         nextleft = t; 
10222                 */
10223                 pic14_emitcode(";remove left +","");
10224         } else
10225                 return 0;
10226         
10227         big = AOP_SIZE(nextleft);
10228         small = AOP_SIZE(nextright);
10229         
10230         switch(nextic->op) {
10231                 
10232         case '+':
10233                 pic14_emitcode(";optimize a +","");
10234                 /* if unsigned or not an integral type */
10235                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10236                         pic14_emitcode(";add a bit to something","");
10237                 } else {
10238                         
10239                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10240                         
10241                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10242                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10243                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10244                         } else
10245                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10246                         
10247                         offset = 0;
10248                         while(--big) {
10249                                 
10250                                 offset++;
10251                                 
10252                                 if(--small) {
10253                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10254                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10255                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10256                                         }
10257                                         
10258                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10259                                         emitSKPNC;
10260                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10261                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10262                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10263                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10264                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10265                                         
10266                                 } else {
10267                                         pic14_emitcode("rlf","known_zero,w");
10268                                         
10269                                         /*
10270                                         if right is signed
10271                                         btfsc  right,7
10272                                         addlw ff
10273                                         */
10274                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10275                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10276                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10277                                         } else {
10278                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10279                                         }
10280                                 }
10281                         }
10282                         ret = 1;
10283                 }
10284         }
10285         ret = 1;
10286         
10287 release:
10288         freeAsmop(right,NULL,ic,TRUE);
10289         freeAsmop(result,NULL,ic,TRUE);
10290         freeAsmop(nextright,NULL,ic,TRUE);
10291         freeAsmop(nextleft,NULL,ic,TRUE);
10292         if(ret)
10293                 nextic->generated = 1;
10294         
10295         return ret;
10296 #else
10297         return 0;
10298 #endif
10299 }
10300 /*-----------------------------------------------------------------*/
10301 /* genCast - gen code for casting                                  */
10302 /*-----------------------------------------------------------------*/
10303 static void genCast (iCode *ic)
10304 {
10305         operand *result = IC_RESULT(ic);
10306         sym_link *ctype = operandType(IC_LEFT(ic));
10307         sym_link *rtype = operandType(IC_RIGHT(ic));
10308         operand *right = IC_RIGHT(ic);
10309         int size, offset ;
10310         
10311         FENTRY;
10312         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10313         /* if they are equivalent then do nothing */
10314         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10315                 return ;
10316         
10317         aopOp(right,ic,FALSE) ;
10318         aopOp(result,ic,FALSE);
10319         
10320         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10321         
10322         /* if the result is a bit */
10323         if (AOP_TYPE(result) == AOP_CRY) {
10324         /* if the right size is a literal then
10325                 we know what the value is */
10326                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10327                 if (AOP_TYPE(right) == AOP_LIT) {
10328                         
10329                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10330                                 popGet(AOP(result),0));
10331                         
10332                         if (((int) operandLitValue(right))) 
10333                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
10334                                 AOP(result)->aopu.aop_dir,
10335                                 AOP(result)->aopu.aop_dir);
10336                         else
10337                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
10338                                 AOP(result)->aopu.aop_dir,
10339                                 AOP(result)->aopu.aop_dir);
10340                         
10341                         goto release;
10342                 }
10343                 
10344                 /* the right is also a bit variable */
10345                 if (AOP_TYPE(right) == AOP_CRY) {
10346                         
10347                         emitCLRC;
10348                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10349                         
10350                         pic14_emitcode("clrc","");
10351                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10352                                 AOP(right)->aopu.aop_dir,
10353                                 AOP(right)->aopu.aop_dir);
10354                         aopPut(AOP(result),"c",0);
10355                         goto release ;
10356                 }
10357                 
10358                 /* we need to or */
10359                 if (AOP_TYPE(right) == AOP_REG) {
10360                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10361                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
10362                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10363                 }
10364                 pic14_toBoolean(right);
10365                 aopPut(AOP(result),"a",0);
10366                 goto release ;
10367         }
10368         
10369         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10370                 int offset = 1;
10371                 size = AOP_SIZE(result);
10372                 
10373                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10374                 
10375                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10376                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10377                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10378                 
10379                 while (size--)
10380                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10381                 
10382                 goto release;
10383         }
10384         
10385         /* if they are the same size : or less */
10386         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10387                 
10388                 /* if they are in the same place */
10389                 if (pic14_sameRegs(AOP(right),AOP(result)))
10390                         goto release;
10391                 
10392                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10393                 if (IS_PTR_CONST(rtype))
10394                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10395                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10396                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10397                 
10398                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10399                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10400                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10401                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10402                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10403                         if(AOP_SIZE(result) <2)
10404                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10405                         
10406                 } else {
10407                         
10408                         /* if they in different places then copy */
10409                         size = AOP_SIZE(result);
10410                         offset = 0 ;
10411                         while (size--) {
10412                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10413                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10414                                 
10415                                 //aopPut(AOP(result),
10416                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10417                                 // offset);
10418                                 
10419                                 offset++;
10420                         }
10421                 }
10422                 goto release;
10423         }
10424         
10425         
10426         /* if the result is of type pointer */
10427         if (IS_PTR(ctype)) {
10428                 
10429                 int p_type;
10430                 sym_link *type = operandType(right);
10431                 sym_link *etype = getSpec(type);
10432                 DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10433                 
10434                 /* pointer to generic pointer */
10435                 if (IS_GENPTR(ctype)) {
10436                         char *l = zero;
10437                         
10438                         if (IS_PTR(type)) 
10439                                 p_type = DCL_TYPE(type);
10440                         else {
10441                                 /* we have to go by the storage class */
10442                                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10443                                 
10444                                 /*    if (SPEC_OCLS(etype)->codesp )  */
10445                                 /*        p_type = CPOINTER ;  */
10446                                 /*    else */
10447                                 /*        if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10448                                 /*      p_type = FPOINTER ; */
10449                                 /*        else */
10450                                 /*      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10451                                 /*          p_type = PPOINTER; */
10452                                 /*      else */
10453                                 /*          if (SPEC_OCLS(etype) == idata ) */
10454                                 /*        p_type = IPOINTER ; */
10455                                 /*          else */
10456                                 /*        p_type = POINTER ; */
10457                         }
10458                         
10459                         /* the first two bytes are known */
10460                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10461                         size = GPTRSIZE - 1; 
10462                         offset = 0 ;
10463                         while (size--) {
10464                                 if(offset < AOP_SIZE(right)) {
10465                                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10466                                         if ((AOP_TYPE(right) == AOP_PCODE) && 
10467                                                 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10468                                                 emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
10469                                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10470                                         } else { 
10471                                                 aopPut(AOP(result),
10472                                                         aopGet(AOP(right),offset,FALSE,FALSE),
10473                                                         offset);
10474                                         }
10475                                 } else 
10476                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
10477                                 offset++;
10478                         }
10479                         /* the last byte depending on type */
10480                         switch (p_type) {
10481                         case IPOINTER:
10482                         case POINTER:
10483                                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
10484                                 break;
10485                         case FPOINTER:
10486                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10487                                 l = one;
10488                                 break;
10489                         case CPOINTER:
10490                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10491                                 l = "#0x02";
10492                                 break;        
10493                         case PPOINTER:
10494                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10495                                 l = "#0x03";
10496                                 break;
10497                                 
10498                         default:
10499                                 /* this should never happen */
10500                                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10501                                         "got unknown pointer type");
10502                                 exit(1);
10503                         }
10504                         //aopPut(AOP(result),l, GPTRSIZE - 1);      
10505                         goto release ;
10506                 }
10507                 
10508                 /* just copy the pointers */
10509                 size = AOP_SIZE(result);
10510                 offset = 0 ;
10511                 while (size--) {
10512                         aopPut(AOP(result),
10513                                 aopGet(AOP(right),offset,FALSE,FALSE),
10514                                 offset);
10515                         offset++;
10516                 }
10517                 goto release ;
10518         }
10519         
10520         
10521         
10522         /* so we now know that the size of destination is greater
10523         than the size of the source.
10524         Now, if the next iCode is an operator then we might be
10525         able to optimize the operation without performing a cast.
10526         */
10527         if(genMixedOperation(ic))
10528                 goto release;
10529         
10530         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10531         
10532         /* we move to result for the size of source */
10533         size = AOP_SIZE(right);
10534         offset = 0 ;
10535         while (size--) {
10536                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10537                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10538                 offset++;
10539         }
10540         
10541         /* now depending on the sign of the destination */
10542         size = AOP_SIZE(result) - AOP_SIZE(right);
10543         /* if unsigned or not an integral type */
10544         if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10545                 while (size--)
10546                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10547         } else {
10548                 /* we need to extend the sign :{ */
10549                 
10550                 if(size == 1) {
10551                         /* Save one instruction of casting char to int */
10552                         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
10553                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10554                         emitpcode(POC_DECF,   popGet(AOP(result),offset));
10555                 } else {
10556                         emitpcodeNULLop(POC_CLRW);
10557                         
10558                         if(offset)
10559                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10560                         else
10561                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10562                         
10563                         emitpcode(POC_MOVLW,   popGetLit(0xff));
10564                         
10565                         while (size--)
10566                                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
10567                 }
10568         }
10569         
10570 release:
10571         freeAsmop(right,NULL,ic,TRUE);
10572         freeAsmop(result,NULL,ic,TRUE);
10573         
10574 }
10575
10576 /*-----------------------------------------------------------------*/
10577 /* genDjnz - generate decrement & jump if not zero instrucion      */
10578 /*-----------------------------------------------------------------*/
10579 static int genDjnz (iCode *ic, iCode *ifx)
10580 {
10581         symbol *lbl, *lbl1;
10582         FENTRY;
10583         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10584         
10585         if (!ifx)
10586                 return 0;
10587         
10588                 /* if the if condition has a false label
10589         then we cannot save */
10590         if (IC_FALSE(ifx))
10591                 return 0;
10592         
10593                 /* if the minus is not of the form 
10594         a = a - 1 */
10595         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10596                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10597                 return 0;
10598         
10599         if (operandLitValue(IC_RIGHT(ic)) != 1)
10600                 return 0;
10601         
10602                 /* if the size of this greater than one then no
10603         saving */
10604         if (getSize(operandType(IC_RESULT(ic))) > 1)
10605                 return 0;
10606         
10607         /* otherwise we can save BIG */
10608         lbl = newiTempLabel(NULL);
10609         lbl1= newiTempLabel(NULL);
10610         
10611         aopOp(IC_RESULT(ic),ic,FALSE);
10612         
10613         if (IS_AOP_PREG(IC_RESULT(ic))) {
10614                 pic14_emitcode("dec","%s",
10615                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10616                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10617                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10618         } else {  
10619                 
10620                 
10621                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10622                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10623                 
10624                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10625                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10626                 
10627         }
10628         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10629         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10630         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10631         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10632         
10633         
10634         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10635         ifx->generated = 1;
10636         return 1;
10637 }
10638
10639 /*-----------------------------------------------------------------*/
10640 /* genReceive - generate code for a receive iCode                  */
10641 /*-----------------------------------------------------------------*/
10642 static void genReceive (iCode *ic)
10643 {
10644         FENTRY;
10645         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10646         
10647         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10648                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10649                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10650                 
10651                 int size = getSize(operandType(IC_RESULT(ic)));
10652                 int offset =  fReturnSizePic - size;
10653                 while (size--) {
10654                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10655                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10656                         offset++;
10657                 }
10658                 aopOp(IC_RESULT(ic),ic,FALSE);
10659                 size = AOP_SIZE(IC_RESULT(ic));
10660                 offset = 0;
10661                 while (size--) {
10662                         pic14_emitcode ("pop","acc");
10663                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10664                 }
10665                 
10666         } else {
10667                 _G.accInUse++;
10668                 aopOp(IC_RESULT(ic),ic,FALSE);
10669                 _G.accInUse--;
10670                 assignResultValue(IC_RESULT(ic));
10671         }
10672         
10673         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10674 }
10675
10676 /*-----------------------------------------------------------------*/
10677 /* genDummyRead - generate code for dummy read of volatiles        */
10678 /*-----------------------------------------------------------------*/
10679 static void
10680 genDummyRead (iCode * ic)
10681 {
10682         FENTRY;
10683         pic14_emitcode ("; genDummyRead","");
10684         pic14_emitcode ("; not implemented","");
10685         
10686         ic = ic;
10687 }
10688
10689 /*-----------------------------------------------------------------*/
10690 /* genpic14Code - generate code for pic14 based controllers        */
10691 /*-----------------------------------------------------------------*/
10692 /*
10693 * At this point, ralloc.c has gone through the iCode and attempted
10694 * to optimize in a way suitable for a PIC. Now we've got to generate
10695 * PIC instructions that correspond to the iCode.
10696 *
10697 * Once the instructions are generated, we'll pass through both the
10698 * peep hole optimizer and the pCode optimizer.
10699 *-----------------------------------------------------------------*/
10700
10701 void genpic14Code (iCode *lic)
10702 {
10703         iCode *ic;
10704         int cln = 0;
10705         const char *cline;
10706         
10707         FENTRY;
10708         lineHead = lineCurr = NULL;
10709         
10710         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10711         addpBlock(pb);
10712         
10713         /* if debug information required */
10714         if (options.debug && currFunc) { 
10715                 if (currFunc) {
10716                         debugFile->writeFunction (currFunc, lic);
10717                 }
10718         }
10719         
10720         
10721         for (ic = lic ; ic ; ic = ic->next ) {
10722                 
10723                 //DEBUGpic14_emitcode(";ic","");
10724                 //fprintf (stderr, "in ic loop\n");
10725                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10726                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10727                 
10728                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10729                   cln = ic->lineno;
10730                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10731                   cline = printCLine (ic->filename, ic->lineno);
10732                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10733                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10734                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10735                 }
10736                 
10737                 if (options.iCodeInAsm) {
10738                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10739                 }
10740                 /* if the result is marked as
10741                 spilt and rematerializable or code for
10742                 this has already been generated then
10743                 do nothing */
10744                 if (resultRemat(ic) || ic->generated ) 
10745                         continue ;
10746                 
10747                 /* depending on the operation */
10748                 switch (ic->op) {
10749                 case '!' :
10750                         genNot(ic);
10751                         break;
10752                         
10753                 case '~' :
10754                         genCpl(ic);
10755                         break;
10756                         
10757                 case UNARYMINUS:
10758                         genUminus (ic);
10759                         break;
10760                         
10761                 case IPUSH:
10762                         genIpush (ic);
10763                         break;
10764                         
10765                 case IPOP:
10766                         /* IPOP happens only when trying to restore a 
10767                         spilt live range, if there is an ifx statement
10768                         following this pop then the if statement might
10769                         be using some of the registers being popped which
10770                         would destory the contents of the register so
10771                         we need to check for this condition and handle it */
10772                         if (ic->next            && 
10773                                 ic->next->op == IFX &&
10774                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10775                                 genIfx (ic->next,ic);
10776                         else
10777                                 genIpop (ic);
10778                         break; 
10779                         
10780                 case CALL:
10781                         genCall (ic);
10782                         break;
10783                         
10784                 case PCALL:
10785                         genPcall (ic);
10786                         break;
10787                         
10788                 case FUNCTION:
10789                         genFunction (ic);
10790                         break;
10791                         
10792                 case ENDFUNCTION:
10793                         genEndFunction (ic);
10794                         break;
10795                         
10796                 case RETURN:
10797                         genRet (ic);
10798                         break;
10799                         
10800                 case LABEL:
10801                         genLabel (ic);
10802                         break;
10803                         
10804                 case GOTO:
10805                         genGoto (ic);
10806                         break;
10807                         
10808                 case '+' :
10809                         genPlus (ic) ;
10810                         break;
10811                         
10812                 case '-' :
10813                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10814                                 genMinus (ic);
10815                         break;
10816                         
10817                 case '*' :
10818                         genMult (ic);
10819                         break;
10820                         
10821                 case '/' :
10822                         genDiv (ic) ;
10823                         break;
10824                         
10825                 case '%' :
10826                         genMod (ic);
10827                         break;
10828                         
10829                 case '>' :
10830                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10831                         break;
10832                         
10833                 case '<' :
10834                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10835                         break;
10836                         
10837                 case LE_OP:
10838                 case GE_OP:
10839                 case NE_OP:
10840                         
10841                         /* note these two are xlated by algebraic equivalence
10842                         during parsing SDCC.y */
10843                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10844                                 "got '>=' or '<=' shouldn't have come here");
10845                         break;  
10846                         
10847                 case EQ_OP:
10848                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10849                         break;      
10850                         
10851                 case AND_OP:
10852                         genAndOp (ic);
10853                         break;
10854                         
10855                 case OR_OP:
10856                         genOrOp (ic);
10857                         break;
10858                         
10859                 case '^' :
10860                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10861                         break;
10862                         
10863                 case '|' :
10864                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10865                         break;
10866                         
10867                 case BITWISEAND:
10868                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10869                         break;
10870                         
10871                 case INLINEASM:
10872                         genInline (ic);
10873                         break;
10874                         
10875                 case RRC:
10876                         genRRC (ic);
10877                         break;
10878                         
10879                 case RLC:
10880                         genRLC (ic);
10881                         break;
10882                         
10883                 case GETHBIT:
10884                         genGetHbit (ic);
10885                         break;
10886                         
10887                 case LEFT_OP:
10888                         genLeftShift (ic);
10889                         break;
10890                         
10891                 case RIGHT_OP:
10892                         genRightShift (ic);
10893                         break;
10894                         
10895                 case GET_VALUE_AT_ADDRESS:
10896                         genPointerGet(ic);
10897                         break;
10898                         
10899                 case '=' :
10900                         if (POINTER_SET(ic))
10901                                 genPointerSet(ic);
10902                         else
10903                                 genAssign(ic);
10904                         break;
10905                         
10906                 case IFX:
10907                         genIfx (ic,NULL);
10908                         break;
10909                         
10910                 case ADDRESS_OF:
10911                         genAddrOf (ic);
10912                         break;
10913                         
10914                 case JUMPTABLE:
10915                         genJumpTab (ic);
10916                         break;
10917                         
10918                 case CAST:
10919                         genCast (ic);
10920                         break;
10921                         
10922                 case RECEIVE:
10923                         genReceive(ic);
10924                         break;
10925                         
10926                 case SEND:
10927                         addSet(&_G.sendSet,ic);
10928                         break;
10929                         
10930                 case DUMMY_READ_VOLATILE:
10931                         genDummyRead (ic);
10932                         break;
10933                         
10934                 default :
10935                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10936                         ic = ic;
10937                         break;
10938                 }
10939         }
10940
10941         
10942         /* now we are ready to call the
10943         peep hole optimizer */
10944         if (!options.nopeep) {
10945                 peepHole (&lineHead);
10946         }
10947         /* now do the actual printing */
10948         printLine (lineHead,codeOutFile);
10949         
10950 #ifdef PCODE_DEBUG
10951         DFPRINTF((stderr,"printing pBlock\n\n"));
10952         printpBlock(stdout,pb);
10953 #endif
10954         
10955         return;
10956 }
10957
10958 int
10959 aop_isLitLike (asmop *aop)
10960 {
10961   assert (aop);
10962   if (aop->type == AOP_LIT) return 1;
10963   if (aop->type == AOP_IMMD) return 1;
10964   if ((aop->type == AOP_PCODE) &&
10965                 ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
10966   {
10967     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10968      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10969     return 1;
10970   }
10971   return 0;
10972 }
10973
10974 int
10975 op_isLitLike (operand *op)
10976 {
10977   assert (op);
10978   if (aop_isLitLike (AOP(op))) return 1;
10979   return 0;
10980 }