* as/hc08/lkaomf51.c (OutputName): made name unsigned char,
[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         /* should have been converted to function call */
3308         //assert(0) ;
3309         
3310 release :
3311         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3312         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3313         freeAsmop(result,NULL,ic,TRUE); 
3314 }
3315
3316 /*-----------------------------------------------------------------*/
3317 /* genDivbits :- division of bits                                                                  */
3318 /*-----------------------------------------------------------------*/
3319 static void genDivbits (operand *left, 
3320                                                 operand *right, 
3321                                                 operand *result)
3322 {
3323         
3324         char *l;
3325         
3326         FENTRY;
3327
3328         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3329         /* the result must be bit */      
3330         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3331         l = aopGet(AOP(left),0,FALSE,FALSE);
3332         
3333         MOVA(l);          
3334         
3335         pic14_emitcode("div","ab");
3336         pic14_emitcode("rrc","a");
3337         aopPut(AOP(result),"c",0);
3338 }
3339
3340 /*-----------------------------------------------------------------*/
3341 /* genDivOneByte : 8 bit division                                                                  */
3342 /*-----------------------------------------------------------------*/
3343 static void genDivOneByte (operand *left,
3344                                                    operand *right,
3345                                                    operand *result)
3346 {
3347         sym_link *opetype = operandType(result);
3348         char *l ;
3349         symbol *lbl ;
3350         int size,offset;
3351         
3352         FENTRY;
3353         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3354         size = AOP_SIZE(result) - 1;
3355         offset = 1;
3356         /* signed or unsigned */
3357         if (SPEC_USIGN(opetype)) {
3358                 /* unsigned is easy */
3359                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3360                 l = aopGet(AOP(left),0,FALSE,FALSE);
3361                 MOVA(l);                
3362                 pic14_emitcode("div","ab");
3363                 aopPut(AOP(result),"a",0);
3364                 while (size--)
3365                         aopPut(AOP(result),zero,offset++);
3366                 return ;
3367         }
3368         
3369         /* signed is a little bit more difficult */
3370         
3371         /* save the signs of the operands */
3372         l = aopGet(AOP(left),0,FALSE,FALSE);      
3373         MOVA(l);          
3374         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,TRUE));
3375         pic14_emitcode("push","acc"); /* save it on the stack */
3376         
3377         /* now sign adjust for both left & right */
3378         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3379         MOVA(l);                 
3380         lbl = newiTempLabel(NULL);
3381         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3382         pic14_emitcode("cpl","a");   
3383         pic14_emitcode("inc","a");
3384         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3385         pic14_emitcode("mov","b,a");
3386         
3387         /* sign adjust left side */
3388         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3389         MOVA(l);
3390         
3391         lbl = newiTempLabel(NULL);
3392         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3393         pic14_emitcode("cpl","a");
3394         pic14_emitcode("inc","a");
3395         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3396         
3397         /* now the division */
3398         pic14_emitcode("div","ab");
3399         /* we are interested in the lower order
3400         only */
3401         pic14_emitcode("mov","b,a");
3402         lbl = newiTempLabel(NULL);
3403         pic14_emitcode("pop","acc");     
3404         /* if there was an over flow we don't 
3405         adjust the sign of the result */
3406         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3407         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3408         CLRC;
3409         pic14_emitcode("clr","a");
3410         pic14_emitcode("subb","a,b");
3411         pic14_emitcode("mov","b,a");
3412         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3413         
3414         /* now we are done */
3415         aopPut(AOP(result),"b",0);
3416         if(size > 0){
3417                 pic14_emitcode("mov","c,b.7");
3418                 pic14_emitcode("subb","a,acc");   
3419         }
3420         while (size--)
3421                 aopPut(AOP(result),"a",offset++);
3422         
3423 }
3424
3425 /*-----------------------------------------------------------------*/
3426 /* genDiv - generates code for division                                                    */
3427 /*-----------------------------------------------------------------*/
3428 static void genDiv (iCode *ic)
3429 {
3430         operand *left = IC_LEFT(ic);
3431         operand *right = IC_RIGHT(ic);
3432         operand *result= IC_RESULT(ic); 
3433         
3434         FENTRY;
3435         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3436         /* assign the amsops */
3437         aopOp (left,ic,FALSE);
3438         aopOp (right,ic,FALSE);
3439         aopOp (result,ic,TRUE);
3440         
3441         /* special cases first */
3442         /* both are bits */
3443         if (AOP_TYPE(left) == AOP_CRY &&
3444                 AOP_TYPE(right)== AOP_CRY) {
3445                 genDivbits(left,right,result);
3446                 goto release ;
3447         }
3448         
3449         /* if both are of size == 1 */
3450         if (AOP_SIZE(left) == 1 &&
3451                 AOP_SIZE(right) == 1 ) {
3452                 genDivOneByte(left,right,result);
3453                 goto release ;
3454         }
3455         
3456         /* should have been converted to function call */
3457         assert(0);
3458 release :
3459         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3460         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3461         freeAsmop(result,NULL,ic,TRUE); 
3462 }
3463
3464 /*-----------------------------------------------------------------*/
3465 /* genModbits :- modulus of bits                                                                   */
3466 /*-----------------------------------------------------------------*/
3467 static void genModbits (operand *left, 
3468                                                 operand *right, 
3469                                                 operand *result)
3470 {
3471         
3472         char *l;
3473         
3474         FENTRY;
3475         /* the result must be bit */      
3476         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3477         l = aopGet(AOP(left),0,FALSE,FALSE);
3478         
3479         MOVA(l);
3480         
3481         pic14_emitcode("div","ab");
3482         pic14_emitcode("mov","a,b");
3483         pic14_emitcode("rrc","a");
3484         aopPut(AOP(result),"c",0);
3485 }
3486
3487 /*-----------------------------------------------------------------*/
3488 /* genModOneByte : 8 bit modulus                                                                   */
3489 /*-----------------------------------------------------------------*/
3490 static void genModOneByte (operand *left,
3491                                                    operand *right,
3492                                                    operand *result)
3493 {
3494         sym_link *opetype = operandType(result);
3495         char *l ;
3496         symbol *lbl ;
3497         
3498         FENTRY;
3499         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3500         /* signed or unsigned */
3501         if (SPEC_USIGN(opetype)) {
3502                 /* unsigned is easy */
3503                 pic14_emitcode("mov","b,%s", aopGet(AOP(right),0,FALSE,FALSE));
3504                 l = aopGet(AOP(left),0,FALSE,FALSE);
3505                 MOVA(l);        
3506                 pic14_emitcode("div","ab");
3507                 aopPut(AOP(result),"b",0);
3508                 return ;
3509         }
3510         
3511         /* signed is a little bit more difficult */
3512         
3513         /* save the signs of the operands */
3514         l = aopGet(AOP(left),0,FALSE,FALSE);      
3515         MOVA(l);
3516         
3517         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),0,FALSE,FALSE));
3518         pic14_emitcode("push","acc"); /* save it on the stack */
3519         
3520         /* now sign adjust for both left & right */
3521         l =  aopGet(AOP(right),0,FALSE,FALSE);  
3522         MOVA(l);
3523         
3524         lbl = newiTempLabel(NULL);
3525         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3526         pic14_emitcode("cpl","a");   
3527         pic14_emitcode("inc","a");
3528         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3529         pic14_emitcode("mov","b,a"); 
3530         
3531         /* sign adjust left side */
3532         l =  aopGet(AOP(left),0,FALSE,FALSE);    
3533         MOVA(l);
3534         
3535         lbl = newiTempLabel(NULL);
3536         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3537         pic14_emitcode("cpl","a");   
3538         pic14_emitcode("inc","a");
3539         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3540         
3541         /* now the multiplication */
3542         pic14_emitcode("div","ab");
3543         /* we are interested in the lower order
3544         only */
3545         lbl = newiTempLabel(NULL);
3546         pic14_emitcode("pop","acc");     
3547         /* if there was an over flow we don't 
3548         adjust the sign of the result */
3549         pic14_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3550         pic14_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3551         CLRC ;
3552         pic14_emitcode("clr","a");
3553         pic14_emitcode("subb","a,b");
3554         pic14_emitcode("mov","b,a");
3555         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
3556         
3557         /* now we are done */
3558         aopPut(AOP(result),"b",0);
3559         
3560 }
3561
3562 /*-----------------------------------------------------------------*/
3563 /* genMod - generates code for division                                                    */
3564 /*-----------------------------------------------------------------*/
3565 static void genMod (iCode *ic)
3566 {
3567         operand *left = IC_LEFT(ic);
3568         operand *right = IC_RIGHT(ic);
3569         operand *result= IC_RESULT(ic);  
3570         
3571         FENTRY;
3572         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3573         /* assign the amsops */
3574         aopOp (left,ic,FALSE);
3575         aopOp (right,ic,FALSE);
3576         aopOp (result,ic,TRUE);
3577         
3578         /* special cases first */
3579         /* both are bits */
3580         if (AOP_TYPE(left) == AOP_CRY &&
3581                 AOP_TYPE(right)== AOP_CRY) {
3582                 genModbits(left,right,result);
3583                 goto release ;
3584         }
3585         
3586         /* if both are of size == 1 */
3587         if (AOP_SIZE(left) == 1 &&
3588                 AOP_SIZE(right) == 1 ) {
3589                 genModOneByte(left,right,result);
3590                 goto release ;
3591         }
3592         
3593         /* should have been converted to function call */
3594         assert(0);
3595         
3596 release :
3597         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3598         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3599         freeAsmop(result,NULL,ic,TRUE); 
3600 }
3601
3602 /*-----------------------------------------------------------------*/
3603 /* genIfxJump :- will create a jump depending on the ifx                   */
3604 /*-----------------------------------------------------------------*/
3605 /*
3606 note: May need to add parameter to indicate when a variable is in bit space.
3607 */
3608 static void genIfxJump (iCode *ic, char *jval)
3609 {
3610         
3611         FENTRY;
3612         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3613         /* if true label then we jump if condition
3614         supplied is true */
3615         if ( IC_TRUE(ic) ) {
3616                 
3617                 if(strcmp(jval,"a") == 0)
3618                         emitSKPZ;
3619                 else if (strcmp(jval,"c") == 0)
3620                         emitSKPC;
3621                 else {
3622                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3623                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3624                 }
3625                 
3626                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3627                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3628                 
3629         }
3630         else {
3631                 /* false label is present */
3632                 if(strcmp(jval,"a") == 0)
3633                         emitSKPNZ;
3634                 else if (strcmp(jval,"c") == 0)
3635                         emitSKPNC;
3636                 else {
3637                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3638                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3639                 }
3640                 
3641                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3642                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3643                 
3644         }
3645         
3646         
3647         /* mark the icode as generated */
3648         ic->generated = 1;
3649 }
3650
3651 /*-----------------------------------------------------------------*/
3652 /* genSkip                                                                                                                 */
3653 /*-----------------------------------------------------------------*/
3654 static void genSkip(iCode *ifx,int status_bit)
3655 {
3656         FENTRY;
3657         if(!ifx)
3658                 return;
3659         
3660         if ( IC_TRUE(ifx) ) {
3661                 switch(status_bit) {
3662                 case 'z':
3663                         emitSKPNZ;
3664                         break;
3665                         
3666                 case 'c':
3667                         emitSKPNC;
3668                         break;
3669                         
3670                 case 'd':
3671                         emitSKPDC;
3672                         break;
3673                         
3674                 }
3675                 
3676                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3677                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3678                 
3679         } else {
3680                 
3681                 switch(status_bit) {
3682                         
3683                 case 'z':
3684                         emitSKPZ;
3685                         break;
3686                         
3687                 case 'c':
3688                         emitSKPC;
3689                         break;
3690                         
3691                 case 'd':
3692                         emitSKPDC;
3693                         break;
3694                 }
3695                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3696                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3697                 
3698         }
3699         
3700 }
3701
3702 /*-----------------------------------------------------------------*/
3703 /* genSkipc                                                                                                        */
3704 /*-----------------------------------------------------------------*/
3705 static void genSkipc(resolvedIfx *rifx)
3706 {
3707         FENTRY;
3708         if(!rifx)
3709                 return;
3710         
3711         if(rifx->condition)
3712                 emitSKPNC;
3713         else
3714                 emitSKPC;
3715         
3716         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3717         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3718         rifx->generated = 1;
3719 }
3720
3721 /*-----------------------------------------------------------------*/
3722 /* genSkipz2                                                                                                       */
3723 /*-----------------------------------------------------------------*/
3724 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3725 {
3726         FENTRY;
3727         if(!rifx)
3728                 return;
3729         
3730         if( (rifx->condition ^ invert_condition) & 1)
3731                 emitSKPZ;
3732         else
3733                 emitSKPNZ;
3734         
3735         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3736         rifx->generated = 1;
3737 }
3738
3739 /*-----------------------------------------------------------------*/
3740 /* genSkipz                                                        */
3741 /*-----------------------------------------------------------------*/
3742 static void genSkipz(iCode *ifx, int condition)
3743 {
3744         FENTRY;
3745         if(!ifx)
3746                 return;
3747         
3748         if(condition)
3749                 emitSKPNZ;
3750         else
3751                 emitSKPZ;
3752         
3753         if ( IC_TRUE(ifx) )
3754                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3755         else
3756                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3757         
3758         if ( IC_TRUE(ifx) )
3759                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3760         else
3761                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3762         
3763 }
3764
3765 #if 0
3766 /*-----------------------------------------------------------------*/
3767 /* genSkipCond                                                     */
3768 /*-----------------------------------------------------------------*/
3769 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3770 {
3771         FENTRY;
3772         if(!rifx)
3773                 return;
3774         
3775         if(rifx->condition)
3776                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3777         else
3778                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3779         
3780         
3781         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3782         rifx->generated = 1;
3783 }
3784 #endif
3785
3786 #if 0
3787 /*-----------------------------------------------------------------*/
3788 /* genChkZeroes :- greater or less than comparison                 */
3789 /*     For each byte in a literal that is zero, inclusive or the   */
3790 /*     the corresponding byte in the operand with W                */
3791 /*     returns true if any of the bytes are zero                   */
3792 /*-----------------------------------------------------------------*/
3793 static int genChkZeroes(operand *op, int lit,  int size)
3794 {
3795         
3796         int i;
3797         int flag =1;
3798         
3799         while(size--) {
3800                 i = (lit >> (size*8)) & 0xff;
3801                 
3802                 if(i==0) {
3803                         if(flag) 
3804                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3805                         else
3806                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3807                         flag = 0;
3808                 }
3809         }
3810         
3811         return (flag==0);
3812 }
3813 #endif
3814
3815
3816 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3817 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3818 #define DEBUGpc           emitpComment
3819
3820 /*-----------------------------------------------------------------*/
3821 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3822 /*                  aop (if it's NOT a literal) or from lit (if    */
3823 /*                  aop is a literal)                              */
3824 /*-----------------------------------------------------------------*/
3825 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3826   if (aop->type == AOP_LIT) {
3827     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3828   } else {
3829     emitpcode (POC_MOVFW, popGet (aop, offset));
3830   }
3831 }
3832
3833 /* genCmp performs a left < right comparison, stores
3834  * the outcome in result (if != NULL) and generates
3835  * control flow code for the ifx (if != NULL).
3836  *
3837  * This version leaves in sequences like
3838  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3839  * which should be optmized by the peephole
3840  * optimizer - RN 2005-01-01 */
3841 static void genCmp (operand *left,operand *right,
3842                     operand *result, iCode *ifx, int sign)
3843 {
3844   resolvedIfx rIfx;
3845   int size;
3846   int offs;
3847   symbol *templbl;
3848   operand *dummy;
3849   unsigned long lit;
3850   unsigned long mask;
3851   int performedLt;
3852   int invert_result = 0;
3853
3854   FENTRY;
3855   
3856   assert (AOP_SIZE(left) == AOP_SIZE(right));
3857   assert (left && right);
3858
3859   size = AOP_SIZE(right) - 1;
3860   mask = (0x100UL << (size*8)) - 1;
3861   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3862   performedLt = 1;
3863   templbl = NULL;
3864   lit = 0;
3865   
3866   resolveIfx (&rIfx, ifx);
3867
3868   /**********************************************************************
3869    * handle bits - bit compares are promoted to int compares seemingly! *
3870    **********************************************************************/
3871 #if 0
3872   // THIS IS COMPLETELY UNTESTED!
3873   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3874     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3875     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3876     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3877
3878     emitSETC;
3879     // 1 < {0,1} is false --> clear C by skipping the next instruction
3880     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3881     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3882     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3883     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3884     emitCLRC; // only skipped for left=0 && right=1
3885
3886     goto correct_result_in_carry;
3887   } // if
3888 #endif
3889
3890   /*************************************************
3891    * make sure that left is register (or the like) *
3892    *************************************************/
3893   if (!isAOP_REGlike(left)) {
3894     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3895     assert (isAOP_LIT(left));
3896     assert (isAOP_REGlike(right));
3897     // swap left and right
3898     // left < right <==> right > left <==> (right >= left + 1)
3899     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
3900
3901     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
3902       // MAXVALUE < right? always false
3903       if (performedLt) emitCLRC; else emitSETC;
3904       goto correct_result_in_carry;
3905     } // if
3906
3907     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
3908     // that's why we handled it above.
3909     lit++;
3910
3911     dummy = left;
3912     left = right;
3913     right = dummy;
3914
3915     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
3916   } else if (isAOP_LIT(right)) {
3917     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3918   } // if
3919
3920   assert (isAOP_REGlike(left)); // left must be register or the like
3921   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
3922
3923   /*************************************************
3924    * special cases go here                         *
3925    *************************************************/
3926
3927   if (isAOP_LIT(right)) {
3928     if (!sign) {
3929       // unsigned comparison to a literal
3930       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
3931       if (lit == 0) {
3932         // unsigned left < 0? always false
3933         if (performedLt) emitCLRC; else emitSETC;
3934         goto correct_result_in_carry;
3935       }
3936     } else {
3937       // signed comparison to a literal
3938       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
3939       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
3940         // signed left < 0x80000000? always false
3941         if (performedLt) emitCLRC; else emitSETC;
3942         goto correct_result_in_carry;
3943       } else if (lit == 0) {
3944         // compare left < 0; set CARRY if SIGNBIT(left) is set
3945         if (performedLt) emitSETC; else emitCLRC;
3946         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
3947         if (performedLt) emitCLRC; else emitSETC;
3948         goto correct_result_in_carry;
3949       }
3950     } // if (!sign)
3951   } // right is literal
3952
3953   /*************************************************
3954    * perform a general case comparison             *
3955    * make sure we get CARRY==1 <==> left >= right  *
3956    *************************************************/
3957   // compare most significant bytes
3958   //DEBUGpc ("comparing bytes at offset %d", size);
3959   if (!sign) {
3960     // unsigned comparison
3961     pic14_mov2w_regOrLit (AOP(right), lit, size);
3962     emitpcode (POC_SUBFW, popGet (AOP(left), size));
3963   } else {
3964     // signed comparison
3965     // (add 2^n to both operands then perform an unsigned comparison)
3966     if (isAOP_LIT(right)) {
3967       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
3968       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
3969
3970       if (litbyte == 0x80) {
3971         // left >= 0x80 -- always true, but more bytes to come
3972         mov2w (AOP(left), size);
3973         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
3974         emitSETC;
3975       } else {
3976         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
3977         mov2w (AOP(left), size);
3978         emitpcode (POC_ADDLW, popGetLit (0x80));
3979         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
3980       } // if
3981     } else {
3982       pCodeOp *pctemp = popGetTempReg();
3983       mov2w (AOP(left), size);
3984       emitpcode (POC_ADDLW, popGetLit (0x80));
3985       emitpcode (POC_MOVWF, pctemp);
3986       mov2w (AOP(right), size);
3987       emitpcode (POC_ADDLW, popGetLit (0x80));
3988       emitpcode (POC_SUBFW, pctemp);
3989       popReleaseTempReg(pctemp);
3990     }
3991   } // if (!sign)
3992
3993   // compare remaining bytes (treat as unsigned case from above)
3994   templbl = newiTempLabel ( NULL );
3995   offs = size;
3996   while (offs--) {
3997     //DEBUGpc ("comparing bytes at offset %d", offs);
3998     emitSKPZ;
3999     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4000     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4001     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4002   } // while (offs)
4003   emitpLabel (templbl->key);
4004   goto result_in_carry;
4005
4006 result_in_carry:
4007   
4008   /****************************************************
4009    * now CARRY contains the result of the comparison: *
4010    * SUBWF sets CARRY iff                             *
4011    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4012    * (F=left, W=right)                                *
4013    ****************************************************/
4014
4015   if (performedLt) {
4016     invert_result = 1;
4017     // value will be used in the following genSkipc()
4018     rIfx.condition ^= 1;
4019   } // if
4020
4021 correct_result_in_carry:
4022
4023   // assign result to variable (if neccessary)
4024   if (result && AOP_TYPE(result) != AOP_CRY) {
4025     //DEBUGpc ("assign result");
4026     size = AOP_SIZE(result);
4027     while (size--) {
4028       emitpcode (POC_CLRF, popGet (AOP(result), size));
4029     } // while
4030     if (invert_result) {
4031       emitSKPC;
4032       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4033     } else {
4034       emitpcode (POC_RLF, popGet (AOP(result), 0));
4035     }
4036   } // if (result)
4037
4038   // perform conditional jump
4039   if (ifx) {
4040     //DEBUGpc ("generate control flow");
4041     genSkipc (&rIfx);
4042     ifx->generated = 1;
4043   } // if
4044 }
4045
4046
4047 #if 0
4048 /* OLD VERSION -- BUGGY, DO NOT USE */
4049
4050 /*-----------------------------------------------------------------*/
4051 /* genCmp :- greater or less than comparison                       */
4052 /*-----------------------------------------------------------------*/
4053 static void genCmp (operand *left,operand *right,
4054                                         operand *result, iCode *ifx, int sign)
4055 {
4056         int size; //, offset = 0 ;
4057         unsigned long lit = 0L,i = 0;
4058         resolvedIfx rFalseIfx;
4059         //  resolvedIfx rTrueIfx;
4060         symbol *truelbl;
4061
4062         FENTRY;
4063         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4064         /*
4065         if(ifx) {
4066         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4067         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4068         }
4069         */
4070         
4071         resolveIfx(&rFalseIfx,ifx);
4072         truelbl  = newiTempLabel(NULL);
4073         size = max(AOP_SIZE(left),AOP_SIZE(right));
4074         
4075         DEBUGpic14_AopType(__LINE__,left,right,result);
4076         
4077 #define _swapp
4078         
4079         /* if literal is on the right then swap with left */
4080         if ((AOP_TYPE(right) == AOP_LIT)) {
4081                 operand *tmp = right ;
4082                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4083                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4084 #ifdef _swapp
4085                 
4086                 lit = (lit - 1) & mask;
4087                 right = left;
4088                 left = tmp;
4089                 rFalseIfx.condition ^= 1;
4090 #endif
4091                 
4092         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4093                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4094         }
4095         
4096         
4097         //if(IC_TRUE(ifx) == NULL)
4098         /* if left & right are bit variables */
4099         if (AOP_TYPE(left) == AOP_CRY &&
4100                 AOP_TYPE(right) == AOP_CRY ) {
4101                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4102                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4103         } else {
4104         /* subtract right from left if at the
4105         end the carry flag is set then we know that
4106                 left is greater than right */
4107                 
4108                 symbol *lbl  = newiTempLabel(NULL);
4109                 
4110 #ifndef _swapp
4111                 if(AOP_TYPE(right) == AOP_LIT) {
4112                         
4113                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4114                         
4115                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4116                         
4117                         /* special cases */
4118                         
4119                         if(lit == 0) {
4120                                 
4121                                 if(sign != 0) 
4122                                         genSkipCond(&rFalseIfx,left,size-1,7);
4123                                 else 
4124                                         /* no need to compare to 0...*/
4125                                         /* NOTE: this is a de-generate compare that most certainly 
4126                                         *       creates some dead code. */
4127                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4128                                 
4129                                 if(ifx) ifx->generated = 1;
4130                                 return;
4131                                 
4132                         }
4133                         size--;
4134                         
4135                         if(size == 0) {
4136                                 //i = (lit >> (size*8)) & 0xff;
4137                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4138                                 
4139                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4140                                 
4141                                 i = ((0-lit) & 0xff);
4142                                 if(sign) {
4143                                         if( i == 0x81) { 
4144                                         /* lit is 0x7f, all signed chars are less than
4145                                                 * this except for 0x7f itself */
4146                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4147                                                 genSkipz2(&rFalseIfx,0);
4148                                         } else {
4149                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4150                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4151                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4152                                         }
4153                                         
4154                                 } else {
4155                                         if(lit == 1) {
4156                                                 genSkipz2(&rFalseIfx,1);
4157                                         } else {
4158                                                 emitpcode(POC_ADDLW, popGetLit(i));
4159                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4160                                         }
4161                                 }
4162                                 
4163                                 if(ifx) ifx->generated = 1;
4164                                 return;
4165                         }
4166                         
4167                         /* chars are out of the way. now do ints and longs */
4168                         
4169                         
4170                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4171                         
4172                         /* special cases */
4173                         
4174                         if(sign) {
4175                                 
4176                                 if(lit == 0) {
4177                                         genSkipCond(&rFalseIfx,left,size,7);
4178                                         if(ifx) ifx->generated = 1;
4179                                         return;
4180                                 }
4181                                 
4182                                 if(lit <0x100) {
4183                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4184                                         
4185                                         //rFalseIfx.condition ^= 1;
4186                                         //genSkipCond(&rFalseIfx,left,size,7);
4187                                         //rFalseIfx.condition ^= 1;
4188                                         
4189                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4190                                         if(rFalseIfx.condition)
4191                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4192                                         else
4193                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4194                                         
4195                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4196                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4197                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4198                                         
4199                                         while(size > 1)
4200                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4201                                         
4202                                         if(rFalseIfx.condition) {
4203                                                 emitSKPZ;
4204                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4205                                                 
4206                                         } else {
4207                                                 emitSKPNZ;
4208                                         }
4209                                         
4210                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4211                                         emitpLabel(truelbl->key);
4212                                         if(ifx) ifx->generated = 1;
4213                                         return;
4214                                         
4215                                 }
4216                                 
4217                                 if(size == 1) {
4218                                         
4219                                         if( (lit & 0xff) == 0) {
4220                                                 /* lower byte is zero */
4221                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4222                                                 i = ((lit >> 8) & 0xff) ^0x80;
4223                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4224                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4225                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4226                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4227                                                 
4228                                                 
4229                                                 if(ifx) ifx->generated = 1;
4230                                                 return;
4231                                                 
4232                                         }
4233                                 } else {
4234                                         /* Special cases for signed longs */
4235                                         if( (lit & 0xffffff) == 0) {
4236                                                 /* lower byte is zero */
4237                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4238                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4239                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4240                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4241                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4242                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4243                                                 
4244                                                 
4245                                                 if(ifx) ifx->generated = 1;
4246                                                 return;
4247                                                 
4248                                         }
4249                                         
4250                                 }
4251                                 
4252                                 
4253                                 if(lit & (0x80 << (size*8))) {
4254                                         /* lit is negative */
4255                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4256                                         
4257                                         //genSkipCond(&rFalseIfx,left,size,7);
4258                                         
4259                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4260                                         
4261                                         if(rFalseIfx.condition)
4262                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4263                                         else
4264                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4265                                         
4266                                         
4267                                 } else {
4268                                         /* lit is positive */
4269                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4270                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4271                                         if(rFalseIfx.condition)
4272                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4273                                         else
4274                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4275                                         
4276                                 }
4277                                 
4278                                 /* There are no more special cases, so perform a general compare */
4279                                 
4280                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4281                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4282                                 
4283                                 while(size--) {
4284                                         
4285                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4286                                         emitSKPNZ;
4287                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4288                                 }
4289                                 //rFalseIfx.condition ^= 1;
4290                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4291                                 
4292                                 emitpLabel(truelbl->key);
4293                                 
4294                                 if(ifx) ifx->generated = 1;
4295                                 return;
4296                                 
4297                                 
4298                         }
4299
4300
4301                         /* sign is out of the way. So now do an unsigned compare */
4302                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4303
4304
4305                         /* General case - compare to an unsigned literal on the right.*/
4306
4307                         i = (lit >> (size*8)) & 0xff;
4308                         emitpcode(POC_MOVLW, popGetLit(i));
4309                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4310                         while(size--) {
4311                                 i = (lit >> (size*8)) & 0xff;
4312                                 
4313                                 if(i) {
4314                                         emitpcode(POC_MOVLW, popGetLit(i));
4315                                         emitSKPNZ;
4316                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4317                                 } else {
4318                                 /* this byte of the lit is zero, 
4319                                         *if it's not the last then OR in the variable */
4320                                         if(size)
4321                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4322                                 }
4323                         }
4324
4325
4326                 emitpLabel(lbl->key);
4327                 //if(emitFinalCheck)
4328                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4329                 if(sign)
4330                         emitpLabel(truelbl->key);
4331
4332                 if(ifx) ifx->generated = 1;
4333                 return;
4334
4335
4336                 }
4337 #endif  // _swapp
4338
4339                 if(AOP_TYPE(left) == AOP_LIT) {
4340                         //symbol *lbl = newiTempLabel(NULL);
4341                         
4342                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4343                         
4344                         
4345                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4346                         
4347                         /* Special cases */
4348                         if((lit == 0) && (sign == 0)){
4349                                 
4350                                 size--;
4351                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4352                                 while(size) 
4353                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4354                                 
4355                                 genSkipz2(&rFalseIfx,0);
4356                                 if(ifx) ifx->generated = 1;
4357                                 return;
4358                         }
4359                         
4360                         if(size==1) {
4361                                 /* Special cases */
4362                                 lit &= 0xff;
4363                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4364                                         /* degenerate compare can never be true */
4365                                         if(rFalseIfx.condition == 0)
4366                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4367                                         
4368                                         if(ifx) ifx->generated = 1;
4369                                         return;
4370                                 }
4371                                 
4372                                 if(sign) {
4373                                         /* signed comparisons to a literal byte */
4374                                         
4375                                         int lp1 = (lit+1) & 0xff;
4376                                         
4377                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4378                                         switch (lp1) {
4379                                         case 0:
4380                                                 rFalseIfx.condition ^= 1;
4381                                                 genSkipCond(&rFalseIfx,right,0,7);
4382                                                 break;
4383                                         case 0x7f:
4384                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4385                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4386                                                 genSkipz2(&rFalseIfx,1);
4387                                                 break;
4388                                         default:
4389                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4390                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4391                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4392                                                 rFalseIfx.condition ^= 1;
4393                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4394                                                 break;
4395                                         }
4396                                         if(ifx) ifx->generated = 1;
4397                                 } else {
4398                                         /* unsigned comparisons to a literal byte */
4399                                         
4400                                         switch(lit & 0xff ) {
4401                                         case 0:
4402                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4403                                                 genSkipz2(&rFalseIfx,0);
4404                                                 if(ifx) ifx->generated = 1;
4405                                                 break;
4406                                         case 0x7f:
4407                                                 genSkipCond(&rFalseIfx,right,0,7);
4408                                                 if(ifx) ifx->generated = 1;
4409                                                 break;
4410                                                 
4411                                         default:
4412                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4413                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4414                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4415                                                 rFalseIfx.condition ^= 1;
4416                                                 if (AOP_TYPE(result) == AOP_CRY) {
4417                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4418                                                         if(ifx) ifx->generated = 1;
4419                                                 } else {
4420                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4421                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4422                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4423                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4424                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4425                                                 }       
4426                                                 break;
4427                                         }
4428                                 }
4429                                 
4430                                 //goto check_carry;
4431                                 return;
4432                                 
4433                         } else {
4434                                 
4435                                 /* Size is greater than 1 */
4436                                 
4437                                 if(sign) {
4438                                         int lp1 = lit+1;
4439                                         
4440                                         size--;
4441                                         
4442                                         if(lp1 == 0) {
4443                                                 /* this means lit = 0xffffffff, or -1 */
4444                                                 
4445                                                 
4446                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4447                                                 rFalseIfx.condition ^= 1;
4448                                                 genSkipCond(&rFalseIfx,right,size,7);
4449                                                 if(ifx) ifx->generated = 1;
4450                                                 return;
4451                                         }
4452                                         
4453                                         if(lit == 0) {
4454                                                 int s = size;
4455                                                 
4456                                                 if(rFalseIfx.condition) {
4457                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4458                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4459                                                 }
4460                                                 
4461                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4462                                                 while(size--)
4463                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4464                                                 
4465                                                 
4466                                                 emitSKPZ;
4467                                                 if(rFalseIfx.condition) {
4468                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4469                                                         emitpLabel(truelbl->key);
4470                                                 }else {
4471                                                         rFalseIfx.condition ^= 1;
4472                                                         genSkipCond(&rFalseIfx,right,s,7);
4473                                                 }
4474                                                 
4475                                                 if(ifx) ifx->generated = 1;
4476                                                 return;
4477                                         }
4478                                         
4479                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4480                                                 /* lower byte of signed word is zero */
4481                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4482                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4483                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4484                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4485                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4486                                                 rFalseIfx.condition ^= 1;
4487                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4488                                                 
4489                                                 
4490                                                 if(ifx) ifx->generated = 1;
4491                                                 return;
4492                                         }
4493                                         
4494                                         if(lit & (0x80 << (size*8))) {
4495                                                 /* Lit is less than zero */
4496                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4497                                                 //rFalseIfx.condition ^= 1;
4498                                                 //genSkipCond(&rFalseIfx,left,size,7);
4499                                                 //rFalseIfx.condition ^= 1;
4500                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4501                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4502                                                 
4503                                                 if(rFalseIfx.condition)
4504                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4505                                                 else
4506                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4507                                                 
4508                                                 
4509                                         } else {
4510                                                 /* Lit is greater than or equal to zero */
4511                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4512                                                 //rFalseIfx.condition ^= 1;
4513                                                 //genSkipCond(&rFalseIfx,right,size,7);
4514                                                 //rFalseIfx.condition ^= 1;
4515                                                 
4516                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4517                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4518                                                 
4519                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4520                                                 if(rFalseIfx.condition)
4521                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4522                                                 else
4523                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4524                                                 
4525                                         }
4526                                         
4527                                         
4528                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4529                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4530                                         
4531                                         while(size--) {
4532                                                 
4533                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4534                                                 emitSKPNZ;
4535                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4536                                         }
4537                                         rFalseIfx.condition ^= 1;
4538                                         //rFalseIfx.condition = 1;
4539                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4540                                         
4541                                         emitpLabel(truelbl->key);
4542                                         
4543                                         if(ifx) ifx->generated = 1;
4544                                         return;
4545                                         // end of if (sign)
4546                                 } else {
4547                                         
4548                                         /* compare word or long to an unsigned literal on the right.*/
4549                                         
4550                                         
4551                                         size--;
4552                                         if(lit < 0xff) {
4553                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4554                                                 switch (lit) {
4555                                                 case 0:
4556                                                         break; /* handled above */
4557                                                 /*
4558                                                 case 0xff:
4559                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4560                                                         while(size--)
4561                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4562                                                         genSkipz2(&rFalseIfx,0);
4563                                                         break;
4564                                                 */
4565                                                 default:
4566                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4567                                                         while(--size)
4568                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4569                                                         
4570                                                         emitSKPZ;
4571                                                         if(rFalseIfx.condition)
4572                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4573                                                         else
4574                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4575                                                         
4576                                                         
4577                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4578                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4579                                                         
4580                                                         rFalseIfx.condition ^= 1;
4581                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4582                                                 }
4583                                                 
4584                                                 emitpLabel(truelbl->key);
4585                                                 
4586                                                 if(ifx) ifx->generated = 1;
4587                                                 return;
4588                                         }
4589                                         
4590                                         
4591                                         lit++;
4592                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4593                                         i = (lit >> (size*8)) & 0xff;
4594                                         
4595                                         emitpcode(POC_MOVLW, popGetLit(i));
4596                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4597                                         
4598                                         while(size--) {
4599                                                 i = (lit >> (size*8)) & 0xff;
4600                                                 
4601                                                 if(i) {
4602                                                         emitpcode(POC_MOVLW, popGetLit(i));
4603                                                         emitSKPNZ;
4604                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4605                                                 } else {
4606                                                 /* this byte of the lit is zero, 
4607                                                         *if it's not the last then OR in the variable */
4608                                                         if(size)
4609                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4610                                                 }
4611                                         }
4612                                         
4613                                         
4614                                         emitpLabel(lbl->key);
4615                                         
4616                                         rFalseIfx.condition ^= 1;
4617                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4618                                 }
4619                                 
4620                                 if(sign)
4621                                         emitpLabel(truelbl->key);
4622                                 if(ifx) ifx->generated = 1;
4623                                 return;
4624                         }
4625                 }
4626                 /* Compare two variables */
4627                 
4628                 DEBUGpic14_emitcode(";sign","%d",sign);
4629                 
4630                 size--;
4631                 if(sign) {
4632                         /* Sigh. thus sucks... */
4633                         if(size) {
4634                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4635                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4636                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4637                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4638                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4639                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4640                         } else {
4641                                 /* Signed char comparison */
4642                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4643                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4644                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4645                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4646                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4647                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4648                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4649                                 
4650                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4651                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4652                                 
4653                                 if(ifx) ifx->generated = 1;
4654                                 return;
4655                         }
4656                         
4657                 } else {
4658                         
4659                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4660                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4661                 }
4662                 
4663                 
4664                 /* The rest of the bytes of a multi-byte compare */
4665                 while (size) {
4666                         
4667                         emitSKPZ;
4668                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4669                         size--;
4670                         
4671                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4672                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4673                         
4674                         
4675                 }
4676                 
4677                 emitpLabel(lbl->key);
4678                 
4679                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4680                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4681                         (AOP_TYPE(result) == AOP_REG)) {
4682                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4683                         emitpcode(POC_RLF, popGet(AOP(result),0));
4684                 } else {
4685                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4686                 }       
4687                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4688                 if(ifx) ifx->generated = 1;
4689                 
4690                 return;
4691                 
4692         }
4693         
4694         // check_carry:
4695         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4696                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4697                 pic14_outBitC(result);
4698         } else {
4699                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4700                 /* if the result is used in the next
4701                 ifx conditional branch then generate
4702                 code a little differently */
4703                 if (ifx )
4704                         genIfxJump (ifx,"c");
4705                 else
4706                         pic14_outBitC(result);
4707                 /* leave the result in acc */
4708         }
4709         
4710 }
4711 #endif
4712
4713 /*-----------------------------------------------------------------*/
4714 /* genCmpGt :- greater than comparison                             */
4715 /*-----------------------------------------------------------------*/
4716 static void genCmpGt (iCode *ic, iCode *ifx)
4717 {
4718         operand *left, *right, *result;
4719         sym_link *letype , *retype;
4720         int sign ;
4721         
4722         FENTRY;
4723         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4724         left = IC_LEFT(ic);
4725         right= IC_RIGHT(ic);
4726         result = IC_RESULT(ic);
4727         
4728         letype = getSpec(operandType(left));
4729         retype =getSpec(operandType(right));
4730         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4731         /* assign the amsops */
4732         aopOp (left,ic,FALSE);
4733         aopOp (right,ic,FALSE);
4734         aopOp (result,ic,TRUE);
4735         
4736         genCmp(right, left, result, ifx, sign);
4737         
4738         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4739         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4740         freeAsmop(result,NULL,ic,TRUE); 
4741 }
4742
4743 /*-----------------------------------------------------------------*/
4744 /* genCmpLt - less than comparisons                                */
4745 /*-----------------------------------------------------------------*/
4746 static void genCmpLt (iCode *ic, iCode *ifx)
4747 {
4748         operand *left, *right, *result;
4749         sym_link *letype , *retype;
4750         int sign ;
4751         
4752         FENTRY;
4753         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4754         left = IC_LEFT(ic);
4755         right= IC_RIGHT(ic);
4756         result = IC_RESULT(ic);
4757         
4758         letype = getSpec(operandType(left));
4759         retype =getSpec(operandType(right));
4760         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4761         
4762         /* assign the amsops */
4763         aopOp (left,ic,FALSE);
4764         aopOp (right,ic,FALSE);
4765         aopOp (result,ic,TRUE);
4766         
4767         genCmp(left, right, result, ifx, sign);
4768         
4769         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4770         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4771         freeAsmop(result,NULL,ic,TRUE); 
4772 }
4773
4774 /*-----------------------------------------------------------------*/
4775 /* genc16bit2lit - compare a 16 bit value to a literal             */
4776 /*-----------------------------------------------------------------*/
4777 static void genc16bit2lit(operand *op, int lit, int offset)
4778 {
4779         int i;
4780         
4781         FENTRY;
4782         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4783         if( (lit&0xff) == 0) 
4784                 i=1;
4785         else
4786                 i=0;
4787         
4788         switch( BYTEofLONG(lit,i)) { 
4789         case 0:
4790                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4791                 break;
4792         case 1:
4793                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4794                 break;
4795         case 0xff:
4796                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4797                 break;
4798         default:
4799                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4800                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4801         }
4802         
4803         i ^= 1;
4804         
4805         switch( BYTEofLONG(lit,i)) { 
4806         case 0:
4807                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4808                 break;
4809         case 1:
4810                 emitSKPNZ;
4811                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4812                 break;
4813         case 0xff:
4814                 emitSKPNZ;
4815                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4816                 break;
4817         default:
4818                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4819                 emitSKPNZ;
4820                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4821                 
4822         }
4823         
4824 }
4825
4826 /*-----------------------------------------------------------------*/
4827 /* gencjneshort - compare and jump if not equal                    */
4828 /*-----------------------------------------------------------------*/
4829 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4830 {
4831         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4832         int offset = 0;
4833         //resolvedIfx rIfx;
4834         symbol *lbl;
4835         
4836         //unsigned long lit = 0L;
4837         FENTRY;
4838         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4839           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4840           return;
4841         }
4842         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4843         DEBUGpic14_AopType(__LINE__,left,right,result);
4844         
4845         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4846         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4847         if (AOP_SIZE(result)) {
4848           for (offset = 0; offset < AOP_SIZE(result); offset++)
4849             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4850         }
4851         
4852         assert (AOP_SIZE(left) == AOP_SIZE(right));
4853         //resolveIfx(&rIfx,ifx);
4854         lbl = newiTempLabel (NULL);
4855         while (size--)
4856         {
4857           mov2w (AOP(right),size);
4858           emitpcode (POC_XORFW, popGet (AOP(left), size));
4859           if (size)
4860           {
4861             emitSKPZ;
4862             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4863           }
4864         } // while
4865         emitpLabel (lbl->key);
4866         if (AOP_SIZE(result)) {
4867           emitSKPNZ;
4868           emitpcode (POC_INCF, popGet (AOP(result), 0));
4869         } else {
4870           assert (ifx);
4871           genSkipz (ifx, NULL != IC_TRUE(ifx));
4872           ifx->generated = 1;
4873         }
4874         return;
4875 #if 0   
4876         if(result)
4877         {
4878                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4879                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4880                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4881                 for (offset=0; offset < AOP_SIZE(result); offset++)
4882                 {
4883                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4884                 } // for offset
4885         }
4886         
4887         
4888         /* if the left side is a literal or 
4889         if the right is in a pointer register and left 
4890         is not */
4891         if ((AOP_TYPE(left) == AOP_LIT) || 
4892                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4893                 operand *t = right;
4894                 right = left;
4895                 left = t;
4896         }
4897         if(AOP_TYPE(right) == AOP_LIT)
4898                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4899         
4900         /* if the right side is a literal then anything goes */
4901         if (AOP_TYPE(right) == AOP_LIT &&
4902                 AOP_TYPE(left) != AOP_DIR ) {
4903                 switch(size) {
4904                 case 2:
4905                         genc16bit2lit(left, lit, 0);
4906                         emitSKPNZ;
4907                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4908                         break;
4909                 default:
4910                         offset = 0;
4911                         while (size--) {
4912                                 if(lit & 0xff) {
4913                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4914                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4915                                 } else {
4916                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
4917                                 }
4918                                 
4919                                 emitSKPNZ;
4920                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
4921                                 offset++;
4922                                 lit >>= 8;
4923                         }
4924                         break;
4925                 }
4926         }
4927         
4928         /* if the right side is in a register or in direct space or
4929         if the left is a pointer register & right is not */    
4930         else if (AOP_TYPE(right) == AOP_REG ||
4931                 AOP_TYPE(right) == AOP_DIR || 
4932                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4933                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4934                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4935                 int lbl_key = lbl->key;
4936                 
4937                 if(!result) {
4938                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4939                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4940                                 __FUNCTION__,__LINE__);
4941                         return;
4942                 }
4943                 
4944                 /*     switch(size) { */
4945                 /*     case 2: */
4946                 /*       genc16bit2lit(left, lit, 0); */
4947                 /*       emitSKPNZ; */
4948                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
4949                 /*       break; */
4950                 /*     default: */
4951                 offset = 0;
4952                 while (size--) {
4953                         int emit_skip=1;
4954                         if((AOP_TYPE(left) == AOP_DIR) && 
4955                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4956                                 
4957                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4958                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
4959                                 
4960                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4961                                 
4962                                 switch (lit & 0xff) {
4963                                 case 0:
4964                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4965                                         break;
4966                                 case 1:
4967                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
4968                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4969                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
4970                                         emit_skip=0;
4971                                         break;
4972                                 case 0xff:
4973                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4974                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
4975                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
4976                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
4977                                         emit_skip=0;
4978                                         break;
4979                                 default:
4980                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
4981                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
4982                                 }
4983                                 lit >>= 8;
4984                                 
4985                         } else {
4986                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
4987                         }
4988                         if(emit_skip) {
4989                                 if(AOP_TYPE(result) == AOP_CRY) {
4990                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4991                                         if(rIfx.condition)
4992                                                 emitSKPNZ;
4993                                         else
4994                                                 emitSKPZ;
4995                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
4996                                 } else {
4997                                         /* fix me. probably need to check result size too */
4998                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
4999                                         if(rIfx.condition)
5000                                                 emitSKPZ;
5001                                         else
5002                                                 emitSKPNZ;
5003                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5004                                 }
5005                                 if(ifx)
5006                                         ifx->generated=1;
5007                         }
5008                         emit_skip++;
5009                         offset++;
5010                 }
5011                 /*       break; */
5012                 /*     } */
5013         } else if(AOP_TYPE(right) == AOP_REG &&
5014                 AOP_TYPE(left) != AOP_DIR){
5015
5016                 offset = 0;
5017                 while(size--) {
5018                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5019                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5020                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5021                         if(rIfx.condition)
5022                                 emitSKPNZ;
5023                         else
5024                                 emitSKPZ;
5025                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5026                         offset++;
5027                 }
5028                 
5029         }else{
5030                 /* right is a pointer reg need both a & b */
5031                 offset = 0;
5032                 while(size--) {
5033                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5034                         if(strcmp(l,"b"))
5035                                 pic14_emitcode("mov","b,%s",l);
5036                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5037                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5038                         offset++;
5039                 }
5040         }
5041         
5042         emitpcode(POC_INCF,popGet(AOP(result),0));
5043         if(!rIfx.condition)
5044                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5045         
5046         emitpLabel(lbl->key);
5047         
5048         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5049         
5050         if(ifx)
5051                 ifx->generated = 1;
5052 #endif
5053 }
5054
5055 #if 0
5056 /*-----------------------------------------------------------------*/
5057 /* gencjne - compare and jump if not equal                         */
5058 /*-----------------------------------------------------------------*/
5059 static void gencjne(operand *left, operand *right, iCode *ifx)
5060 {
5061         symbol *tlbl  = newiTempLabel(NULL);
5062         
5063         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5064         gencjneshort(left, right, lbl);
5065         
5066         pic14_emitcode("mov","a,%s",one);
5067         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5068         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5069         pic14_emitcode("clr","a");
5070         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5071         
5072         emitpLabel(lbl->key);
5073         emitpLabel(tlbl->key);
5074         
5075 }
5076 #endif
5077
5078 /*-----------------------------------------------------------------*/
5079 /* genCmpEq - generates code for equal to                          */
5080 /*-----------------------------------------------------------------*/
5081 static void genCmpEq (iCode *ic, iCode *ifx)
5082 {
5083         operand *left, *right, *result;
5084         unsigned long lit = 0L;
5085         int size,offset=0;
5086         
5087         FENTRY;
5088         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5089         
5090         if(ifx)
5091                 DEBUGpic14_emitcode ("; ifx is non-null","");
5092         else
5093                 DEBUGpic14_emitcode ("; ifx is null","");
5094         
5095         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5096         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5097         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5098         
5099         size = max(AOP_SIZE(left),AOP_SIZE(right));
5100         
5101         DEBUGpic14_AopType(__LINE__,left,right,result);
5102         
5103         /* if literal, literal on the right or 
5104         if the right is in a pointer register and left 
5105         is not */
5106         if (aop_isLitLike (AOP(IC_LEFT(ic)))
5107                         || (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5108                 operand *tmp = right ;
5109                 right = left;
5110                 left = tmp;
5111         }
5112         
5113         
5114         if(ifx && !AOP_SIZE(result)){
5115                 symbol *tlbl;
5116                 /* if they are both bit variables */
5117                 if (AOP_TYPE(left) == AOP_CRY &&
5118                         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5119                         if(AOP_TYPE(right) == AOP_LIT){
5120                                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5121                                 if(lit == 0L){
5122                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5123                                         pic14_emitcode("cpl","c");
5124                                 } else if(lit == 1L) {
5125                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5126                                 } else {
5127                                         pic14_emitcode("clr","c");
5128                                 }
5129                                 /* AOP_TYPE(right) == AOP_CRY */
5130                         } else {
5131                                 symbol *lbl = newiTempLabel(NULL);
5132                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5133                                 pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5134                                 pic14_emitcode("cpl","c");
5135                                 pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5136                         }
5137                         /* if true label then we jump if condition
5138                         supplied is true */
5139                         tlbl = newiTempLabel(NULL);
5140                         if ( IC_TRUE(ifx) ) {
5141                                 pic14_emitcode("jnc","%05d_DS_",tlbl->key+100);
5142                                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5143                         } else {
5144                                 pic14_emitcode("jc","%05d_DS_",tlbl->key+100);
5145                                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5146                         }
5147                         pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5148                         
5149                         {
5150                                 /* left and right are both bit variables, result is carry */
5151                                 resolvedIfx rIfx;
5152                                 
5153                                 resolveIfx(&rIfx,ifx);
5154                                 
5155                                 emitpcode(POC_MOVLW,popGet(AOP(left),0));
5156                                 emitpcode(POC_ANDFW,popGet(AOP(left),0));
5157                                 emitpcode(POC_BTFSC,popGet(AOP(right),0));
5158                                 emitpcode(POC_ANDLW,popGet(AOP(left),0));
5159                                 genSkipz2(&rIfx,0);
5160                         }
5161                 } else {
5162                         
5163                         /* They're not both bit variables. Is the right a literal? */
5164                         if(AOP_TYPE(right) == AOP_LIT) {
5165                                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5166                                 
5167                                 switch(size) {
5168                                         
5169                                 case 1:
5170                                         switch(lit & 0xff) {
5171                                         case 1:
5172                                                 if ( IC_TRUE(ifx) ) {
5173                                                         emitpcode(POC_DECFW,popGet(AOP(left),offset));
5174                                                         emitSKPNZ;
5175                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5176                                                 } else {
5177                                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5178                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5179                                                 }
5180                                                 break;
5181                                         case 0xff:
5182                                                 if ( IC_TRUE(ifx) ) {
5183                                                         emitpcode(POC_INCFW,popGet(AOP(left),offset));
5184                                                         emitSKPNZ;
5185                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5186                                                 } else {
5187                                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5188                                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5189                                                 }
5190                                                 break;
5191                                         default:
5192                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5193                                                 if(lit)
5194                                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5195                                                 genSkip(ifx,'z');
5196                                         }
5197                                         
5198                                         
5199                                         /* end of size == 1 */
5200                                         break;
5201                                         
5202                                         case 2:
5203                                                 genc16bit2lit(left,lit,offset);
5204                                                 genSkip(ifx,'z');
5205                                                 break;
5206                                                 /* end of size == 2 */
5207                                                 
5208                                         default:
5209                                                 /* size is 4 */
5210                                                 if(lit==0) {
5211                                                         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5212                                                         emitpcode(POC_IORFW,popGet(AOP(left),1));
5213                                                         emitpcode(POC_IORFW,popGet(AOP(left),2));
5214                                                         emitpcode(POC_IORFW,popGet(AOP(left),3));
5215                                                         
5216                                                 } else {
5217                                                         
5218                                                         /* search for patterns that can be optimized */
5219                                                         
5220                                                         genc16bit2lit(left,lit,0);
5221                                                         lit >>= 16;
5222                                                         if(lit) {
5223                                                                 genSkipz(ifx,IC_TRUE(ifx) == NULL);
5224                                                                 //genSkip(ifx,'z');
5225                                                                 genc16bit2lit(left,lit,2);
5226                                                         } else {
5227                                                                 emitpcode(POC_IORFW,popGet(AOP(left),2));
5228                                                                 emitpcode(POC_IORFW,popGet(AOP(left),3));
5229                                                                 
5230                                                         }
5231                                                         
5232                                                 }
5233                                                 
5234                                                 genSkip(ifx,'z');
5235                                 }
5236                                 
5237                                 ifx->generated = 1;
5238                                 goto release ;
5239                                 
5240                                 
5241                         } else if(AOP_TYPE(right) == AOP_CRY ) {
5242                                 /* we know the left is not a bit, but that the right is */
5243                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5244                                 emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5245                                         popGet(AOP(right),offset));
5246                                 emitpcode(POC_XORLW,popGetLit(1));
5247                                 
5248                                 /* if the two are equal, then W will be 0 and the Z bit is set
5249                                 * we could test Z now, or go ahead and check the high order bytes if
5250                                 * the variable we're comparing is larger than a byte. */
5251                                 
5252                                 while(--size)
5253                                         emitpcode(POC_IORFW,popGet(AOP(left),offset));
5254                                 
5255                                 if ( IC_TRUE(ifx) ) {
5256                                         emitSKPNZ;
5257                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5258                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5259                                 } else {
5260                                         emitSKPZ;
5261                                         emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5262                                         pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5263                                 }
5264                                 
5265                         } else {
5266                                 /* They're both variables that are larger than bits */
5267                                 int s = size;
5268                                 
5269                                 tlbl = newiTempLabel(NULL);
5270                                 
5271                                 while(size--) {
5272                                         mov2w (AOP(right),offset); /* right might be litLike() */
5273                                         emitpcode(POC_XORFW,popGet(AOP(left),offset));
5274                                         
5275                                         if ( IC_TRUE(ifx) ) {
5276                                                 if(size) {
5277                                                         emitSKPZ;
5278                                                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
5279                                                         pic14_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5280                                                 } else {
5281                                                         emitSKPNZ;
5282                                                         emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5283                                                         pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5284                                                 }
5285                                         } else {
5286                                                 emitSKPZ;
5287                                                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
5288                                                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5289                                         }
5290                                         offset++;
5291                                 }
5292                                 if(s>1 && IC_TRUE(ifx)) {
5293                                         emitpLabel(tlbl->key);
5294                                         pic14_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5295                                 }
5296                         }
5297                 }
5298                 /* mark the icode as generated */
5299                 ifx->generated = 1;
5300                 goto release ;
5301         }
5302   
5303   /* if they are both bit variables */
5304   if (AOP_TYPE(left) == AOP_CRY &&
5305           ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5306           if(AOP_TYPE(right) == AOP_LIT){
5307                   unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5308                   if(lit == 0L){
5309                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5310                           pic14_emitcode("cpl","c");
5311                   } else if(lit == 1L) {
5312                           pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5313                   } else {
5314                           pic14_emitcode("clr","c");
5315                   }
5316                   /* AOP_TYPE(right) == AOP_CRY */
5317           } else {
5318                   symbol *lbl = newiTempLabel(NULL);
5319                   pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5320                   pic14_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5321                   pic14_emitcode("cpl","c");
5322                   pic14_emitcode("","%05d_DS_:",(lbl->key+100));
5323           }
5324           /* c = 1 if egal */
5325           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5326                   pic14_outBitC(result);
5327                   goto release ;
5328           }
5329           if (ifx) {
5330                   genIfxJump (ifx,"c");
5331                   goto release ;
5332           }
5333           /* if the result is used in an arithmetic operation
5334           then put the result in place */
5335           pic14_outBitC(result);
5336   } else {
5337           
5338           DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5339           gencjne(left,right,result,ifx);
5340           /*
5341           if(ifx) 
5342           gencjne(left,right,newiTempLabel(NULL));
5343           else {
5344           if(IC_TRUE(ifx)->key)
5345           gencjne(left,right,IC_TRUE(ifx)->key);
5346           else
5347           gencjne(left,right,IC_FALSE(ifx)->key);
5348           ifx->generated = 1;
5349           goto release ;
5350           }
5351           if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5352           aopPut(AOP(result),"a",0);
5353           goto release ;
5354           }
5355           
5356                 if (ifx) {
5357                 genIfxJump (ifx,"a");
5358                 goto release ;
5359                 }
5360           */
5361           /* if the result is used in an arithmetic operation
5362           then put the result in place */
5363           /*
5364           if (AOP_TYPE(result) != AOP_CRY) 
5365           pic14_outAcc(result);
5366           */
5367           /* leave the result in acc */
5368   }
5369   
5370 release:
5371   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5372   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5373   freeAsmop(result,NULL,ic,TRUE);
5374 }
5375
5376 /*-----------------------------------------------------------------*/
5377 /* ifxForOp - returns the icode containing the ifx for operand     */
5378 /*-----------------------------------------------------------------*/
5379 static iCode *ifxForOp ( operand *op, iCode *ic )
5380 {
5381         FENTRY;
5382         /* if true symbol then needs to be assigned */
5383         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5384         if (IS_TRUE_SYMOP(op))
5385                 return NULL ;
5386         
5387         /* if this has register type condition and
5388         the next instruction is ifx with the same operand
5389         and live to of the operand is upto the ifx only then */
5390         if (ic->next &&
5391                 ic->next->op == IFX &&
5392                 IC_COND(ic->next)->key == op->key &&
5393                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5394                 return ic->next;
5395         
5396         if (ic->next &&
5397                 ic->next->op == IFX &&
5398                 IC_COND(ic->next)->key == op->key) {
5399                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5400                 return ic->next;
5401         }
5402         
5403         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5404         if (ic->next &&
5405                 ic->next->op == IFX)
5406                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5407         
5408         if (ic->next &&
5409                 ic->next->op == IFX &&
5410                 IC_COND(ic->next)->key == op->key) {
5411                 DEBUGpic14_emitcode ("; "," key is okay");
5412                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5413                         OP_SYMBOL(op)->liveTo,
5414                         ic->next->seq);
5415         }
5416         
5417         
5418         return NULL;
5419 }
5420 /*-----------------------------------------------------------------*/
5421 /* genAndOp - for && operation                                     */
5422 /*-----------------------------------------------------------------*/
5423 static void genAndOp (iCode *ic)
5424 {
5425         operand *left,*right, *result;
5426         /*     symbol *tlbl; */
5427         
5428         FENTRY;
5429         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5430         /* note here that && operations that are in an
5431         if statement are taken away by backPatchLabels
5432         only those used in arthmetic operations remain */
5433         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5434         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5435         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5436         
5437         DEBUGpic14_AopType(__LINE__,left,right,result);
5438         
5439         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5440         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5441         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5442         
5443         /* if both are bit variables */
5444         /*     if (AOP_TYPE(left) == AOP_CRY && */
5445         /*         AOP_TYPE(right) == AOP_CRY ) { */
5446         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5447         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5448         /*         pic14_outBitC(result); */
5449         /*     } else { */
5450         /*         tlbl = newiTempLabel(NULL); */
5451         /*         pic14_toBoolean(left);     */
5452         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5453         /*         pic14_toBoolean(right); */
5454         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5455         /*         pic14_outBitAcc(result); */
5456         /*     } */
5457         
5458         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5459         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5460         freeAsmop(result,NULL,ic,TRUE);
5461 }
5462
5463
5464 /*-----------------------------------------------------------------*/
5465 /* genOrOp - for || operation                                      */
5466 /*-----------------------------------------------------------------*/
5467 /*
5468 tsd pic port -
5469 modified this code, but it doesn't appear to ever get called
5470 */
5471
5472 static void genOrOp (iCode *ic)
5473 {
5474         operand *left,*right, *result;
5475         symbol *tlbl;
5476         
5477         /* note here that || operations that are in an
5478         if statement are taken away by backPatchLabels
5479         only those used in arthmetic operations remain */
5480         FENTRY;
5481         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5482         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5483         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5484         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5485         
5486         DEBUGpic14_AopType(__LINE__,left,right,result);
5487         
5488         /* if both are bit variables */
5489         if (AOP_TYPE(left) == AOP_CRY &&
5490                 AOP_TYPE(right) == AOP_CRY ) {
5491                 pic14_emitcode("clrc","");
5492                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5493                         AOP(left)->aopu.aop_dir,
5494                         AOP(left)->aopu.aop_dir);
5495                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5496                         AOP(right)->aopu.aop_dir,
5497                         AOP(right)->aopu.aop_dir);
5498                 pic14_emitcode("setc","");
5499                 
5500         } else {
5501                 tlbl = newiTempLabel(NULL);
5502                 pic14_toBoolean(left);
5503                 emitSKPZ;
5504                 pic14_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5505                 pic14_toBoolean(right);
5506                 pic14_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5507                 
5508                 pic14_outBitAcc(result);
5509         }
5510         
5511         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5512         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5513         freeAsmop(result,NULL,ic,TRUE);            
5514 }
5515
5516 /*-----------------------------------------------------------------*/
5517 /* isLiteralBit - test if lit == 2^n                               */
5518 /*-----------------------------------------------------------------*/
5519 static int isLiteralBit(unsigned long lit)
5520 {
5521         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5522                 0x100L,0x200L,0x400L,0x800L,
5523                 0x1000L,0x2000L,0x4000L,0x8000L,
5524                 0x10000L,0x20000L,0x40000L,0x80000L,
5525                 0x100000L,0x200000L,0x400000L,0x800000L,
5526                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5527                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5528         int idx;
5529         
5530         FENTRY;
5531         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5532         for(idx = 0; idx < 32; idx++)
5533                 if(lit == pw[idx])
5534                         return idx+1;
5535                 return 0;
5536 }
5537
5538 /*-----------------------------------------------------------------*/
5539 /* continueIfTrue -                                                */
5540 /*-----------------------------------------------------------------*/
5541 static void continueIfTrue (iCode *ic)
5542 {
5543         FENTRY;
5544         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5545         if(IC_TRUE(ic))
5546                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5547         ic->generated = 1;
5548 }
5549
5550 /*-----------------------------------------------------------------*/
5551 /* jmpIfTrue -                                                     */
5552 /*-----------------------------------------------------------------*/
5553 static void jumpIfTrue (iCode *ic)
5554 {
5555         FENTRY;
5556         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5557         if(!IC_TRUE(ic))
5558                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5559         ic->generated = 1;
5560 }
5561
5562 /*-----------------------------------------------------------------*/
5563 /* jmpTrueOrFalse -                                                */
5564 /*-----------------------------------------------------------------*/
5565 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5566 {
5567         FENTRY;
5568         // ugly but optimized by peephole
5569         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5570         if(IC_TRUE(ic)){
5571                 symbol *nlbl = newiTempLabel(NULL);
5572                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5573                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5574                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5575                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5576         }
5577         else{
5578                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5579                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5580         }
5581         ic->generated = 1;
5582 }
5583
5584 /*-----------------------------------------------------------------*/
5585 /* genAnd  - code for and                                          */
5586 /*-----------------------------------------------------------------*/
5587 static void genAnd (iCode *ic, iCode *ifx)
5588 {
5589         operand *left, *right, *result;
5590         int size, offset=0;  
5591         unsigned long lit = 0L;
5592         int bytelit = 0;
5593         resolvedIfx rIfx;
5594         
5595         FENTRY;
5596         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5597         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5598         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5599         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5600         
5601         resolveIfx(&rIfx,ifx);
5602         
5603         /* if left is a literal & right is not then exchange them */
5604         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5605                 AOP_NEEDSACC(left)) {
5606                 operand *tmp = right ;
5607                 right = left;
5608                 left = tmp;
5609         }
5610         
5611         /* if result = right then exchange them */
5612         if(pic14_sameRegs(AOP(result),AOP(right))){
5613                 operand *tmp = right ;
5614                 right = left;
5615                 left = tmp;
5616         }
5617         
5618         /* if right is bit then exchange them */
5619         if (AOP_TYPE(right) == AOP_CRY &&
5620                 AOP_TYPE(left) != AOP_CRY){
5621                 operand *tmp = right ;
5622                 right = left;
5623                 left = tmp;
5624         }
5625         if(AOP_TYPE(right) == AOP_LIT)
5626                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5627         
5628         size = AOP_SIZE(result);
5629         
5630         DEBUGpic14_AopType(__LINE__,left,right,result);
5631         
5632         // if(bit & yy)
5633         // result = bit & yy;
5634         if (AOP_TYPE(left) == AOP_CRY){
5635                 // c = bit & literal;
5636                 if(AOP_TYPE(right) == AOP_LIT){
5637                         if(lit & 1) {
5638                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5639                                         // no change
5640                                         goto release;
5641                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5642                         } else {
5643                                 // bit(result) = 0;
5644                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5645                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5646                                         goto release;
5647                                 }
5648                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5649                                         jumpIfTrue(ifx);
5650                                         goto release;
5651                                 }
5652                                 pic14_emitcode("clr","c");
5653                         }
5654                 } else {
5655                         if (AOP_TYPE(right) == AOP_CRY){
5656                                 // c = bit & bit;
5657                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5658                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5659                         } else {
5660                                 // c = bit & val;
5661                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5662                                 // c = lsb
5663                                 pic14_emitcode("rrc","a");
5664                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5665                         }
5666                 }
5667                 // bit = c
5668                 // val = c
5669                 if(size)
5670                         pic14_outBitC(result);
5671                 // if(bit & ...)
5672                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5673                         genIfxJump(ifx, "c");           
5674                 goto release ;
5675         }
5676         
5677         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5678         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5679         if((AOP_TYPE(right) == AOP_LIT) &&
5680                 (AOP_TYPE(result) == AOP_CRY) &&
5681                 (AOP_TYPE(left) != AOP_CRY)){
5682                 int posbit = isLiteralBit(lit);
5683                 /* left &  2^n */
5684                 if(posbit){
5685                         posbit--;
5686                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5687                         // bit = left & 2^n
5688                         if(size)
5689                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5690                         // if(left &  2^n)
5691                         else{
5692                                 if(ifx){
5693                                         int offset = 0;
5694                                         while (posbit > 7) {
5695                                                 posbit -= 8;
5696                                                 offset++;
5697                                         }
5698                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5699                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5700                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5701                                         
5702                                         ifx->generated = 1;
5703                                 }
5704                                 goto release;
5705                         }
5706                 } else {
5707                         symbol *tlbl = newiTempLabel(NULL);
5708                         int sizel = AOP_SIZE(left);
5709                         if(size)
5710                                 pic14_emitcode("setb","c");
5711                         while(sizel--){
5712                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5713                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5714                                         // byte ==  2^n ?
5715                                         if((posbit = isLiteralBit(bytelit)) != 0)
5716                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5717                                         else{
5718                                                 if(bytelit != 0x0FFL)
5719                                                         pic14_emitcode("anl","a,%s",
5720                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5721                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5722                                         }
5723                                 }
5724                                 offset++;
5725                         }
5726                         // bit = left & literal
5727                         if(size){
5728                                 pic14_emitcode("clr","c");
5729                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5730                         }
5731                         // if(left & literal)
5732                         else{
5733                                 if(ifx)
5734                                         jmpTrueOrFalse(ifx, tlbl);
5735                                 goto release ;
5736                         }
5737                 }
5738                 pic14_outBitC(result);
5739                 goto release ;
5740         }
5741         
5742         /* if left is same as result */
5743         if(pic14_sameRegs(AOP(result),AOP(left))){
5744                 int know_W = -1;
5745                 for(;size--; offset++,lit>>=8) {
5746                         if(AOP_TYPE(right) == AOP_LIT){
5747                                 switch(lit & 0xff) {
5748                                 case 0x00:
5749                                         /*  and'ing with 0 has clears the result */
5750                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5751                                         break;
5752                                 case 0xff:
5753                                         /* and'ing with 0xff is a nop when the result and left are the same */
5754                                         break;
5755                                         
5756                                 default:
5757                                         {
5758                                                 int p = my_powof2( (~lit) & 0xff );
5759                                                 if(p>=0) {
5760                                                         /* only one bit is set in the literal, so use a bcf instruction */
5761                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5762                                                         
5763                                                 } else {
5764                                                         if(know_W != (int)(lit&0xff))
5765                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5766                                                         know_W = lit &0xff;
5767                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5768                                                 }
5769                                         }    
5770                                 }
5771                         } else {
5772                                 if (AOP_TYPE(left) == AOP_ACC) {
5773                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5774                                 } else {        
5775                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5776                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5777                                         
5778                                 }
5779                         }
5780                 }
5781                 
5782         } else {
5783                 // left & result in different registers
5784                 if(AOP_TYPE(result) == AOP_CRY){
5785                         // result = bit
5786                         // if(size), result in bit
5787                         // if(!size && ifx), conditional oper: if(left & right)
5788                         symbol *tlbl = newiTempLabel(NULL);
5789                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5790                         if(size)
5791                                 pic14_emitcode("setb","c");
5792                         while(sizer--){
5793                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5794                                 pic14_emitcode("anl","a,%s",
5795                                         aopGet(AOP(left),offset,FALSE,FALSE));
5796                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5797                                 offset++;
5798                         }
5799                         if(size){
5800                                 CLRC;
5801                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5802                                 pic14_outBitC(result);
5803                         } else if(ifx)
5804                                 jmpTrueOrFalse(ifx, tlbl);
5805                 } else {
5806                         for(;(size--);offset++) {
5807                                 // normal case
5808                                 // result = left & right
5809                                 if(AOP_TYPE(right) == AOP_LIT){
5810                                         int t = (lit >> (offset*8)) & 0x0FFL;
5811                                         switch(t) { 
5812                                         case 0x00:
5813                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5814                                                 break;
5815                                         case 0xff:
5816                                                 if(AOP_TYPE(left) != AOP_ACC) {
5817                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5818                                                 }
5819                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5820                                                 break;
5821                                         default:
5822                                                 if(AOP_TYPE(left) == AOP_ACC) {
5823                                                         emitpcode(POC_ANDLW, popGetLit(t));
5824                                                 } else {
5825                                                         emitpcode(POC_MOVLW, popGetLit(t));
5826                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5827                                                 }
5828                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5829                                         }
5830                                         continue;
5831                                 }
5832                                 
5833                                 if (AOP_TYPE(left) == AOP_ACC) {
5834                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5835                                 } else {
5836                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5837                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5838                                 }
5839                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5840                         }
5841                 }
5842         }
5843         
5844 release :
5845         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5846         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5847         freeAsmop(result,NULL,ic,TRUE);     
5848 }
5849
5850 /*-----------------------------------------------------------------*/
5851 /* genOr  - code for or                                            */
5852 /*-----------------------------------------------------------------*/
5853 static void genOr (iCode *ic, iCode *ifx)
5854 {
5855         operand *left, *right, *result;
5856         int size, offset=0;
5857         unsigned long lit = 0L;
5858         
5859         FENTRY;
5860         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5861         
5862         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5863         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5864         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5865         
5866         DEBUGpic14_AopType(__LINE__,left,right,result);
5867         
5868         /* if left is a literal & right is not then exchange them */
5869         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5870                 AOP_NEEDSACC(left)) {
5871                 operand *tmp = right ;
5872                 right = left;
5873                 left = tmp;
5874         }
5875         
5876         /* if result = right then exchange them */
5877         if(pic14_sameRegs(AOP(result),AOP(right))){
5878                 operand *tmp = right ;
5879                 right = left;
5880                 left = tmp;
5881         }
5882         
5883         /* if right is bit then exchange them */
5884         if (AOP_TYPE(right) == AOP_CRY &&
5885                 AOP_TYPE(left) != AOP_CRY){
5886                 operand *tmp = right ;
5887                 right = left;
5888                 left = tmp;
5889         }
5890         
5891         DEBUGpic14_AopType(__LINE__,left,right,result);
5892         
5893         if(AOP_TYPE(right) == AOP_LIT)
5894                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5895         
5896         size = AOP_SIZE(result);
5897         
5898         // if(bit | yy)
5899         // xx = bit | yy;
5900         if (AOP_TYPE(left) == AOP_CRY){
5901                 if(AOP_TYPE(right) == AOP_LIT){
5902                         // c = bit & literal;
5903                         if(lit){
5904                                 // lit != 0 => result = 1
5905                                 if(AOP_TYPE(result) == AOP_CRY){
5906                                         if(size)
5907                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5908                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5909                                         //   AOP(result)->aopu.aop_dir,
5910                                         //   AOP(result)->aopu.aop_dir);
5911                                         else if(ifx)
5912                                                 continueIfTrue(ifx);
5913                                         goto release;
5914                                 }
5915                         } else {
5916                                 // lit == 0 => result = left
5917                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5918                                         goto release;
5919                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5920                         }
5921                 } else {
5922                         if (AOP_TYPE(right) == AOP_CRY){
5923                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5924                                         // c = bit | bit;
5925                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5926                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5927                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5928                                         
5929                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5930                                                 AOP(result)->aopu.aop_dir,
5931                                                 AOP(result)->aopu.aop_dir);
5932                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5933                                                 AOP(right)->aopu.aop_dir,
5934                                                 AOP(right)->aopu.aop_dir);
5935                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5936                                                 AOP(result)->aopu.aop_dir,
5937                                                 AOP(result)->aopu.aop_dir);
5938                                 } else {
5939                                         if( AOP_TYPE(result) == AOP_ACC) {
5940                                                 emitpcode(POC_MOVLW, popGetLit(0));
5941                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5942                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5943                                                 emitpcode(POC_MOVLW, popGetLit(1));
5944                                                 
5945                                         } else {
5946                                                 
5947                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5948                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5949                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5950                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5951                                                 
5952                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5953                                                         AOP(result)->aopu.aop_dir,
5954                                                         AOP(result)->aopu.aop_dir);
5955                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5956                                                         AOP(right)->aopu.aop_dir,
5957                                                         AOP(right)->aopu.aop_dir);
5958                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5959                                                         AOP(left)->aopu.aop_dir,
5960                                                         AOP(left)->aopu.aop_dir);
5961                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5962                                                         AOP(result)->aopu.aop_dir,
5963                                                         AOP(result)->aopu.aop_dir);
5964                                         }
5965                                 }
5966                         } else {
5967                                 // c = bit | val;
5968                                 symbol *tlbl = newiTempLabel(NULL);
5969                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5970                                 
5971                                 
5972                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5973                                 if( AOP_TYPE(right) == AOP_ACC) {
5974                                         emitpcode(POC_IORLW, popGetLit(0));
5975                                         emitSKPNZ;
5976                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5977                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5978                                 }
5979                                 
5980                                 
5981                                 
5982                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5983                                         pic14_emitcode(";XXX setb","c");
5984                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5985                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5986                                 pic14_toBoolean(right);
5987                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5988                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5989                                         jmpTrueOrFalse(ifx, tlbl);
5990                                         goto release;
5991                                 } else {
5992                                         CLRC;
5993                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5994                                 }
5995                         }
5996                 }
5997                 // bit = c
5998                 // val = c
5999                 if(size)
6000                         pic14_outBitC(result);
6001                 // if(bit | ...)
6002                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6003                         genIfxJump(ifx, "c");           
6004                 goto release ;
6005         }
6006
6007         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6008         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6009         if((AOP_TYPE(right) == AOP_LIT) &&
6010           (AOP_TYPE(result) == AOP_CRY) &&
6011           (AOP_TYPE(left) != AOP_CRY)){
6012                 if(lit){
6013                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6014                         // result = 1
6015                         if(size)
6016                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6017                         else 
6018                                 continueIfTrue(ifx);
6019                         goto release;
6020                 } else {
6021                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6022                         // lit = 0, result = boolean(left)
6023                         if(size)
6024                                 pic14_emitcode(";XXX setb","c");
6025                         pic14_toBoolean(right);
6026                         if(size){
6027                                 symbol *tlbl = newiTempLabel(NULL);
6028                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6029                                 CLRC;
6030                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6031                         } else {
6032                                 genIfxJump (ifx,"a");
6033                                 goto release;
6034                         }
6035                 }
6036                 pic14_outBitC(result);
6037                 goto release ;
6038         }
6039
6040         /* if left is same as result */
6041         if(pic14_sameRegs(AOP(result),AOP(left))){
6042                 int know_W = -1;
6043                 for(;size--; offset++,lit>>=8) {
6044                         if(AOP_TYPE(right) == AOP_LIT){
6045                                 if((lit & 0xff) == 0)
6046                                         /*  or'ing with 0 has no effect */
6047                                         continue;
6048                                 else {
6049                                         int p = my_powof2(lit & 0xff);
6050                                         if(p>=0) {
6051                                                 /* only one bit is set in the literal, so use a bsf instruction */
6052                                                 emitpcode(POC_BSF,
6053                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6054                                         } else {
6055                                                 if(know_W != (int)(lit & 0xff))
6056                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6057                                                 know_W = lit & 0xff;
6058                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6059                                         }
6060                                         
6061                                 }
6062                         } else {
6063                                 if (AOP_TYPE(left) == AOP_ACC) {
6064                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
6065                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6066                                 } else {        
6067                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
6068                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
6069                                         
6070                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6071                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6072                                         
6073                                 }
6074                         }
6075                 }
6076         } else {
6077                 // left & result in different registers
6078                 if(AOP_TYPE(result) == AOP_CRY){
6079                         // result = bit
6080                         // if(size), result in bit
6081                         // if(!size && ifx), conditional oper: if(left | right)
6082                         symbol *tlbl = newiTempLabel(NULL);
6083                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6084                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6085                         
6086                         
6087                         if(size)
6088                                 pic14_emitcode(";XXX setb","c");
6089                         while(sizer--){
6090                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6091                                 pic14_emitcode(";XXX orl","a,%s",
6092                                         aopGet(AOP(left),offset,FALSE,FALSE));
6093                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6094                                 offset++;
6095                         }
6096                         if(size){
6097                                 CLRC;
6098                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6099                                 pic14_outBitC(result);
6100                         } else if(ifx)
6101                                 jmpTrueOrFalse(ifx, tlbl);
6102                 } else for(;(size--);offset++){
6103                         // normal case
6104                         // result = left | right
6105                         if(AOP_TYPE(right) == AOP_LIT){
6106                                 int t = (lit >> (offset*8)) & 0x0FFL;
6107                                 switch(t) { 
6108                                 case 0x00:
6109                                         if (AOP_TYPE(left) != AOP_ACC) {
6110                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6111                                         }
6112                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6113                                         
6114                                         break;
6115                                 default:
6116                                         if (AOP_TYPE(left) == AOP_ACC) {
6117                                                 emitpcode(POC_IORLW,  popGetLit(t));
6118                                         } else {
6119                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6120                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6121                                         }
6122                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6123                                 }
6124                                 continue;
6125                         }
6126                         
6127                         // faster than result <- left, anl result,right
6128                         // and better if result is SFR
6129                         if (AOP_TYPE(left) == AOP_ACC) {
6130                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6131                         } else {
6132                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6133                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6134                         }
6135                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6136                 }
6137         }
6138
6139 release :
6140         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6141         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6142         freeAsmop(result,NULL,ic,TRUE);     
6143 }
6144
6145 /*-----------------------------------------------------------------*/
6146 /* genXor - code for xclusive or                                   */
6147 /*-----------------------------------------------------------------*/
6148 static void genXor (iCode *ic, iCode *ifx)
6149 {
6150         operand *left, *right, *result;
6151         int size, offset=0;
6152         unsigned long lit = 0L;
6153         
6154         FENTRY;
6155         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6156         
6157         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6158         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6159         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6160         
6161         /* if left is a literal & right is not ||
6162         if left needs acc & right does not */
6163         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6164                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6165                 operand *tmp = right ;
6166                 right = left;
6167                 left = tmp;
6168         }
6169         
6170         /* if result = right then exchange them */
6171         if(pic14_sameRegs(AOP(result),AOP(right))){
6172                 operand *tmp = right ;
6173                 right = left;
6174                 left = tmp;
6175         }
6176         
6177         /* if right is bit then exchange them */
6178         if (AOP_TYPE(right) == AOP_CRY &&
6179                 AOP_TYPE(left) != AOP_CRY){
6180                 operand *tmp = right ;
6181                 right = left;
6182                 left = tmp;
6183         }
6184         if(AOP_TYPE(right) == AOP_LIT)
6185                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6186         
6187         size = AOP_SIZE(result);
6188         
6189         // if(bit ^ yy)
6190         // xx = bit ^ yy;
6191         if (AOP_TYPE(left) == AOP_CRY){
6192                 if(AOP_TYPE(right) == AOP_LIT){
6193                         // c = bit & literal;
6194                         if(lit>>1){
6195                                 // lit>>1  != 0 => result = 1
6196                                 if(AOP_TYPE(result) == AOP_CRY){
6197                                         if(size)
6198                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6199                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6200                                         else if(ifx)
6201                                                 continueIfTrue(ifx);
6202                                         goto release;
6203                                 }
6204                                 pic14_emitcode("setb","c");
6205                         } else{
6206                                 // lit == (0 or 1)
6207                                 if(lit == 0){
6208                                         // lit == 0, result = left
6209                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6210                                                 goto release;
6211                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6212                                 } else{
6213                                         // lit == 1, result = not(left)
6214                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6215                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6216                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6217                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6218                                                 goto release;
6219                                         } else {
6220                                                 assert ( !"incomplete genXor" );
6221                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6222                                                 pic14_emitcode("cpl","c");
6223                                         }
6224                                 }
6225                         }
6226                         
6227                 } else {
6228                         // right != literal
6229                         symbol *tlbl = newiTempLabel(NULL);
6230                         if (AOP_TYPE(right) == AOP_CRY){
6231                                 // c = bit ^ bit;
6232                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6233                         }
6234                         else{
6235                                 int sizer = AOP_SIZE(right);
6236                                 // c = bit ^ val
6237                                 // if val>>1 != 0, result = 1
6238                                 pic14_emitcode("setb","c");
6239                                 while(sizer){
6240                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6241                                         if(sizer == 1)
6242                                                 // test the msb of the lsb
6243                                                 pic14_emitcode("anl","a,#0xfe");
6244                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6245                                         sizer--;
6246                                 }
6247                                 // val = (0,1)
6248                                 pic14_emitcode("rrc","a");
6249                         }
6250                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6251                         pic14_emitcode("cpl","c");
6252                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6253                 }
6254                 // bit = c
6255                 // val = c
6256                 if(size)
6257                         pic14_outBitC(result);
6258                 // if(bit | ...)
6259                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6260                         genIfxJump(ifx, "c");           
6261                 goto release ;
6262         }
6263         
6264         if(pic14_sameRegs(AOP(result),AOP(left))){
6265                 /* if left is same as result */
6266                 for(;size--; offset++) {
6267                         if(AOP_TYPE(right) == AOP_LIT){
6268                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6269                                 if(t == 0x00L)
6270                                         continue;
6271                                 else
6272                                         if (IS_AOP_PREG(left)) {
6273                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6274                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6275                                                 aopPut(AOP(result),"a",offset);
6276                                         } else {
6277                                                 emitpcode(POC_MOVLW, popGetLit(t));
6278                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6279                                                 pic14_emitcode("xrl","%s,%s",
6280                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6281                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6282                                         }
6283                         } else {
6284                                 if (AOP_TYPE(left) == AOP_ACC)
6285                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6286                                 else {
6287                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6288                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6289                                         /*
6290                                         if (IS_AOP_PREG(left)) {
6291                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6292                                         aopPut(AOP(result),"a",offset);
6293                                         } else
6294                                         pic14_emitcode("xrl","%s,a",
6295                                         aopGet(AOP(left),offset,FALSE,TRUE));
6296                                         */
6297                                 }
6298                         }
6299                 }
6300         } else {
6301                 // left & result in different registers
6302                 if(AOP_TYPE(result) == AOP_CRY){
6303                         // result = bit
6304                         // if(size), result in bit
6305                         // if(!size && ifx), conditional oper: if(left ^ right)
6306                         symbol *tlbl = newiTempLabel(NULL);
6307                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6308                         if(size)
6309                                 pic14_emitcode("setb","c");
6310                         while(sizer--){
6311                                 if((AOP_TYPE(right) == AOP_LIT) &&
6312                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6313                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6314                                 } else {
6315                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6316                                         pic14_emitcode("xrl","a,%s",
6317                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6318                                 }
6319                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6320                                 offset++;
6321                         }
6322                         if(size){
6323                                 CLRC;
6324                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6325                                 pic14_outBitC(result);
6326                         } else if(ifx)
6327                                 jmpTrueOrFalse(ifx, tlbl);
6328                 } else for(;(size--);offset++){
6329                         // normal case
6330                         // result = left & right
6331                         if(AOP_TYPE(right) == AOP_LIT){
6332                                 int t = (lit >> (offset*8)) & 0x0FFL;
6333                                 switch(t) { 
6334                                 case 0x00:
6335                                         if (AOP_TYPE(left) != AOP_ACC) {
6336                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6337                                         }
6338                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6339                                         pic14_emitcode("movf","%s,w",
6340                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6341                                         pic14_emitcode("movwf","%s",
6342                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6343                                         break;
6344                                 case 0xff:
6345                                         if (AOP_TYPE(left) == AOP_ACC) {
6346                                                 emitpcode(POC_XORLW, popGetLit(t));
6347                                         } else {
6348                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6349                                         }
6350                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6351                                         break;
6352                                 default:
6353                                         if (AOP_TYPE(left) == AOP_ACC) {
6354                                                 emitpcode(POC_XORLW, popGetLit(t));
6355                                         } else {
6356                                                 emitpcode(POC_MOVLW, popGetLit(t));
6357                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6358                                         }
6359                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6360                                         pic14_emitcode("movlw","0x%x",t);
6361                                         pic14_emitcode("xorwf","%s,w",
6362                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6363                                         pic14_emitcode("movwf","%s",
6364                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6365                                         
6366                                 }
6367                                 continue;
6368                         }
6369                         
6370                         // faster than result <- left, anl result,right
6371                         // and better if result is SFR
6372                         if (AOP_TYPE(left) == AOP_ACC) {
6373                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6374                         } else {
6375                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6376                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6377                         }
6378                         if ( AOP_TYPE(result) != AOP_ACC){
6379                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6380                         }
6381                 }
6382         }
6383         
6384 release :
6385         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6386         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6387         freeAsmop(result,NULL,ic,TRUE);     
6388 }
6389
6390 /*-----------------------------------------------------------------*/
6391 /* genInline - write the inline code out                           */
6392 /*-----------------------------------------------------------------*/
6393 static void genInline (iCode *ic)
6394 {
6395   char *buffer, *bp, *bp1;
6396
6397   FENTRY;
6398   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6399
6400   _G.inLine += (!options.asmpeep);
6401
6402   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6403   strcpy(buffer,IC_INLINE(ic));
6404
6405   /* emit each line as a code */
6406   while (*bp) {
6407     if (*bp == '\n') {
6408       *bp++ = '\0';
6409       
6410       if(*bp1)
6411         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6412       bp1 = bp;
6413     } else {
6414       if (*bp == ':') {
6415         bp++;
6416         *bp = '\0';
6417         bp++;
6418
6419         /* print label, use this special format with NULL directive
6420          * to denote that the argument should not be indented with tab */
6421         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6422
6423         bp1 = bp;
6424       } else
6425         bp++;
6426     }
6427   }
6428   if ((bp1 != bp) && *bp1)
6429     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6430
6431   Safe_free(buffer);
6432
6433   _G.inLine -= (!options.asmpeep);
6434 }
6435
6436 /*-----------------------------------------------------------------*/
6437 /* genRRC - rotate right with carry                                */
6438 /*-----------------------------------------------------------------*/
6439 static void genRRC (iCode *ic)
6440 {
6441         operand *left , *result ;
6442         int size, offset = 0, same;
6443         
6444         FENTRY;
6445         /* rotate right with carry */
6446         left = IC_LEFT(ic);
6447         result=IC_RESULT(ic);
6448         aopOp (left,ic,FALSE);
6449         aopOp (result,ic,FALSE);
6450         
6451         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6452         
6453         same = pic14_sameRegs(AOP(result),AOP(left));
6454         
6455         size = AOP_SIZE(result);    
6456         
6457         /* get the lsb and put it into the carry */
6458         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6459         
6460         offset = 0 ;
6461         
6462         while(size--) {
6463                 
6464                 if(same) {
6465                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6466                 } else {
6467                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6468                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6469                 }
6470                 
6471                 offset++;
6472         }
6473         
6474         freeAsmop(left,NULL,ic,TRUE);
6475         freeAsmop(result,NULL,ic,TRUE);
6476 }
6477
6478 /*-----------------------------------------------------------------*/
6479 /* genRLC - generate code for rotate left with carry               */
6480 /*-----------------------------------------------------------------*/
6481 static void genRLC (iCode *ic)
6482 {    
6483         operand *left , *result ;
6484         int size, offset = 0;
6485         int same;
6486         
6487         FENTRY;
6488         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6489         /* rotate right with carry */
6490         left = IC_LEFT(ic);
6491         result=IC_RESULT(ic);
6492         aopOp (left,ic,FALSE);
6493         aopOp (result,ic,FALSE);
6494         
6495         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6496         
6497         same = pic14_sameRegs(AOP(result),AOP(left));
6498         
6499         /* move it to the result */
6500         size = AOP_SIZE(result);    
6501         
6502         /* get the msb and put it into the carry */
6503         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6504         
6505         offset = 0 ;
6506         
6507         while(size--) {
6508                 
6509                 if(same) {
6510                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6511                 } else {
6512                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6513                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6514                 }
6515                 
6516                 offset++;
6517         }
6518         
6519         
6520         freeAsmop(left,NULL,ic,TRUE);
6521         freeAsmop(result,NULL,ic,TRUE);
6522 }
6523
6524 /*-----------------------------------------------------------------*/
6525 /* genGetHbit - generates code get highest order bit               */
6526 /*-----------------------------------------------------------------*/
6527 static void genGetHbit (iCode *ic)
6528 {
6529         operand *left, *result;
6530         left = IC_LEFT(ic);
6531         result=IC_RESULT(ic);
6532         aopOp (left,ic,FALSE);
6533         aopOp (result,ic,FALSE);
6534         
6535         FENTRY;
6536         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6537         /* get the highest order byte into a */
6538         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6539         if(AOP_TYPE(result) == AOP_CRY){
6540                 pic14_emitcode("rlc","a");
6541                 pic14_outBitC(result);
6542         }
6543         else{
6544                 pic14_emitcode("rl","a");
6545                 pic14_emitcode("anl","a,#0x01");
6546                 pic14_outAcc(result);
6547         }
6548         
6549         
6550         freeAsmop(left,NULL,ic,TRUE);
6551         freeAsmop(result,NULL,ic,TRUE);
6552 }
6553
6554 /*-----------------------------------------------------------------*/
6555 /* AccRol - rotate left accumulator by known count                 */
6556 /*-----------------------------------------------------------------*/
6557 static void AccRol (operand *op,int offset,int shCount)
6558 {
6559         FENTRY;
6560         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6561         shCount &= 0x0007;              // shCount : 0..7
6562         switch(shCount){
6563         case 0 :
6564                 break;
6565         case 1 :
6566                 pic14_emitcode("rl","a");
6567                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6568                 break;
6569         case 2 :
6570                 pic14_emitcode("rl","a");
6571                 pic14_emitcode("rl","a");
6572                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6573                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6574                 break;
6575         case 3 :
6576                 pic14_emitcode("swap","a");
6577                 pic14_emitcode("rr","a");
6578                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6579                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6580                 break;
6581         case 4 :
6582                 pic14_emitcode("swap","a");
6583                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6584                 break;
6585         case 5 :
6586                 pic14_emitcode("swap","a");
6587                 pic14_emitcode("rl","a");
6588                 emitpcode(POC_SWAPF,popGet(AOP(op),offset));
6589                 emitpcode(POC_RLF,popGet(AOP(op),offset));
6590                 break;
6591         case 6 :
6592                 pic14_emitcode("rr","a");
6593                 pic14_emitcode("rr","a");
6594                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6595                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6596                 break;
6597         case 7 :
6598                 pic14_emitcode("rr","a");
6599                 emitpcode(POC_RRF,popGet(AOP(op),offset));
6600                 break;
6601         }
6602 }
6603
6604 /*-----------------------------------------------------------------*/
6605 /* AccLsh - left shift accumulator by known count                  */
6606 /*-----------------------------------------------------------------*/
6607 static void AccLsh (operand *op,int offset,int shCount)
6608 {
6609         FENTRY;
6610         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6611         if(shCount != 0) {
6612                 if (shCount == 1)
6613                 {
6614                         emitCLRC;
6615                         emitpcode (POC_RLF, popGet (AOP(op), 0));
6616                 } else {
6617                         /* rotate left accumulator */
6618                         AccRol(op,offset,shCount);
6619                         /* and kill the lower order bits */
6620                         emitpcode(POC_MOVLW,popGetLit(SLMask[shCount]));
6621                         emitpcode (POC_ANDWF, popGet (AOP(op),0));
6622                 }
6623         }
6624 }
6625
6626 /*-----------------------------------------------------------------*/
6627 /* AccRsh - right shift accumulator by known count                 */
6628 /*-----------------------------------------------------------------*/
6629 static void AccRsh (operand *op,int offset,int shCount)
6630 {
6631         FENTRY;
6632         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6633         if(shCount != 0){
6634                 if(shCount == 1){
6635                         emitCLRC;
6636                         emitpcode (POC_RRF, popGet (AOP(op), 0));
6637                 } else {
6638                         /* rotate right accumulator */
6639                         AccRol(op,offset,8 - shCount);
6640                         /* and kill the higher order bits */
6641                         emitpcode (POC_MOVLW, popGetLit (SRMask[shCount]));
6642                         emitpcode (POC_ANDWF, popGet (AOP(op),0));
6643                 }
6644         }
6645 }
6646
6647 #if 0
6648 /*-----------------------------------------------------------------*/
6649 /* AccSRsh - signed right shift accumulator by known count                 */
6650 /*-----------------------------------------------------------------*/
6651 static void AccSRsh (int shCount)
6652 {
6653         symbol *tlbl ;
6654         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6655         if(shCount != 0){
6656                 if(shCount == 1){
6657                         pic14_emitcode("mov","c,acc.7");
6658                         pic14_emitcode("rrc","a");
6659                 } else if(shCount == 2){
6660                         pic14_emitcode("mov","c,acc.7");
6661                         pic14_emitcode("rrc","a");
6662                         pic14_emitcode("mov","c,acc.7");
6663                         pic14_emitcode("rrc","a");
6664                 } else {
6665                         tlbl = newiTempLabel(NULL);
6666                         /* rotate right accumulator */
6667                         AccRol(8 - shCount);
6668                         /* and kill the higher order bits */
6669                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6670                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6671                         pic14_emitcode("orl","a,#0x%02x",
6672                                 (unsigned char)~SRMask[shCount]);
6673                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6674                 }
6675         }
6676 }
6677
6678 /*-----------------------------------------------------------------*/
6679 /* shiftR1Left2Result - shift right one byte from left to result   */
6680 /*-----------------------------------------------------------------*/
6681 static void shiftR1Left2ResultSigned (operand *left, int offl,
6682                                                                           operand *result, int offr,
6683                                                                           int shCount)
6684 {
6685         int same;
6686         
6687         FENTRY;
6688         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6689         
6690         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6691         
6692         switch(shCount) {
6693         case 1:
6694                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6695                 if(same) 
6696                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6697                 else {
6698                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6699                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6700                 }
6701                 
6702                 break;
6703         case 2:
6704                 
6705                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6706                 if(same) 
6707                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6708                 else {
6709                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6710                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6711                 }
6712                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6713                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6714                 
6715                 break;
6716                 
6717         case 3:
6718                 if(same)
6719                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6720                 else {
6721                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6722                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6723                 }
6724                 
6725                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6726                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6727                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6728                 
6729                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6730                 emitpcode(POC_IORLW, popGetLit(0xe0));
6731                 
6732                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6733                 break;
6734                 
6735         case 4:
6736                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6737                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6738                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6739                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6740                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6741                 break;
6742         case 5:
6743                 if(same) {
6744                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6745                 } else {
6746                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6747                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6748                 }
6749                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6750                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6751                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6752                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6753                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6754                 break;
6755                 
6756         case 6:
6757                 if(same) {
6758                         emitpcode(POC_MOVLW, popGetLit(0x00));
6759                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6760                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6761                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6762                         emitpcode(POC_IORLW, popGetLit(0x01));
6763                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6764                 } else {
6765                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6766                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6767                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6768                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6769                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6770                 }
6771                 break;
6772                 
6773         case 7:
6774                 if(same) {
6775                         emitpcode(POC_MOVLW, popGetLit(0x00));
6776                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6777                         emitpcode(POC_MOVLW, popGetLit(0xff));
6778                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6779                 } else {
6780                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6781                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6782                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6783                 }
6784                 
6785         default:
6786                 break;
6787         }
6788 }
6789
6790 /*-----------------------------------------------------------------*/
6791 /* shiftR1Left2Result - shift right one byte from left to result   */
6792 /*-----------------------------------------------------------------*/
6793 static void shiftR1Left2Result (operand *left, int offl,
6794                                                                 operand *result, int offr,
6795                                                                 int shCount, int sign)
6796 {
6797         int same;
6798         
6799         FENTRY;
6800         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6801         
6802         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6803         
6804         /* Copy the msb into the carry if signed. */
6805         if(sign) {
6806                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6807                 return;
6808         }
6809         
6810         
6811         
6812         switch(shCount) {
6813         case 1:
6814                 emitCLRC;
6815                 if(same) 
6816                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6817                 else {
6818                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6819                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6820                 }
6821                 break;
6822         case 2:
6823                 emitCLRC;
6824                 if(same) {
6825                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6826                 } else {
6827                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6828                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6829                 }
6830                 emitCLRC;
6831                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6832                 
6833                 break;
6834         case 3:
6835                 if(same)
6836                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6837                 else {
6838                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6839                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6840                 }
6841                 
6842                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6843                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6844                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6845                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6846                 break;
6847                 
6848         case 4:
6849                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6850                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6851                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6852                 break;
6853                 
6854         case 5:
6855                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6856                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6857                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6858                 emitCLRC;
6859                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6860                 
6861                 break;
6862         case 6:
6863                 
6864                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6865                 emitpcode(POC_ANDLW, popGetLit(0x80));
6866                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6867                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6868                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6869                 break;
6870                 
6871         case 7:
6872                 
6873                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6874                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6875                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6876                 
6877                 break;
6878                 
6879         default:
6880                 break;
6881         }
6882 }
6883
6884 /*-----------------------------------------------------------------*/
6885 /* shiftL1Left2Result - shift left one byte from left to result    */
6886 /*-----------------------------------------------------------------*/
6887 static void shiftL1Left2Result (operand *left, int offl,
6888                                                                 operand *result, int offr, int shCount)
6889 {
6890         int same;
6891         
6892         //    char *l;
6893         FENTRY;
6894         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6895         
6896         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6897         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6898         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6899         //    MOVA(l);
6900         /* shift left accumulator */
6901         //AccLsh(shCount); // don't comment out just yet...
6902         //    aopPut(AOP(result),"a",offr);
6903         
6904         switch(shCount) {
6905         case 1:
6906                 /* Shift left 1 bit position */
6907                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6908                 if(same) {
6909                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6910                 } else {
6911                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6912                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6913                 }
6914                 break;
6915         case 2:
6916                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6917                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6918                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6919                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6920                 break;
6921         case 3:
6922                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6923                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6924                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6925                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6926                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6927                 break;
6928         case 4:
6929                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6930                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6931                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6932                 break;
6933         case 5:
6934                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6935                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6936                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6937                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6938                 break;
6939         case 6:
6940                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6941                 emitpcode(POC_ANDLW, popGetLit(0x30));
6942                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6943                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6944                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6945                 break;
6946         case 7:
6947                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6948                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6949                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6950                 break;
6951                 
6952         default:
6953                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6954         }
6955         
6956 }
6957 #endif
6958
6959 /*-----------------------------------------------------------------*/
6960 /* movLeft2Result - move byte from left to result                  */
6961 /*-----------------------------------------------------------------*/
6962 static void movLeft2Result (operand *left, int offl,
6963                                                         operand *result, int offr)
6964 {
6965         char *l;
6966         FENTRY;
6967         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6968         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6969                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6970                 
6971                 if (*l == '@' && (IS_AOP_PREG(result))) {
6972                         pic14_emitcode("mov","a,%s",l);
6973                         aopPut(AOP(result),"a",offr);
6974                 } else {
6975                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6976                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6977                 }
6978         }
6979 }
6980
6981 /*-----------------------------------------------------------------*/
6982 /* shiftLeft_Left2ResultLit - shift left by known count            */
6983 /*-----------------------------------------------------------------*/
6984
6985 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6986 {
6987         int size, same, offr, i;
6988
6989         size = AOP_SIZE(left);
6990         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6991         
6992         same = pic14_sameRegs (AOP(left), AOP(result));
6993         
6994         offr = shCount / 8;
6995         shCount = shCount & 0x07;
6996
6997         size -= offr;
6998
6999         switch (shCount)
7000         {
7001         case 0: /* takes 0 or 2N cycles (for offr==0) */
7002                 if (!same || offr) {
7003                         for (i=size-1; i >= 0; i--)
7004                                 movLeft2Result (left, i, result, offr + i);
7005                 } // if
7006                 break;
7007                 
7008         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
7009                 if (same && offr) {
7010                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
7011                         shiftLeft_Left2ResultLit (result, result, shCount);
7012                         return; /* prevent clearing result again */
7013                 } else {
7014                         emitCLRC;
7015                         for (i=0; i < size; i++) {
7016                                 if (same && !offr) {
7017                                         emitpcode (POC_RLF, popGet (AOP(left), i));
7018                                 } else {
7019                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
7020                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7021                                 } // if
7022                         } // for
7023                 } // if (offr)
7024                 break;
7025                 
7026         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7027                 /* works in-place/with offr as well */
7028                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7029                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7030                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7031
7032                 for (i = size - 2; i >= 0; i--)
7033                 {
7034                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7035                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7036                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7037                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7038                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7039                 } // for i
7040                 break;
7041                 
7042         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7043                 /* works in-place/with offr as well */
7044                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7045                 for (i = size-2; i >= 0; i--) {
7046                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7047                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7048                 } // for i
7049                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7050                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7051                 break;
7052         
7053         default:
7054                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7055                 shiftLeft_Left2ResultLit (result, result, 1);
7056                 return; /* prevent clearing result again */
7057                 break;
7058         } // switch
7059
7060         while (0 < offr--)
7061         {
7062                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7063         } // while
7064 }
7065
7066 /*-----------------------------------------------------------------*/
7067 /* shiftRight_Left2ResultLit - shift right by known count          */
7068 /*-----------------------------------------------------------------*/
7069
7070 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7071 {
7072         int size, same, offr, i;
7073
7074         size = AOP_SIZE(left);
7075         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7076         
7077         same = pic14_sameRegs (AOP(left), AOP(result));
7078         
7079         offr = shCount / 8;
7080         shCount = shCount & 0x07;
7081
7082         size -= offr;
7083
7084         if (size)
7085         {
7086                 switch (shCount)
7087                 {
7088                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7089                         if (!same || offr) {
7090                                 for (i=0; i < size; i++)
7091                                         movLeft2Result (left, i + offr, result, i);
7092                         } // if
7093                         break;
7094                         
7095                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7096                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7097                         if (same && offr) {
7098                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7099                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7100                                 return; /* prevent sign-extending result again */
7101                         } else {
7102                                 emitCLRC;
7103                                 if (sign) {
7104                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7105                                         emitSETC;
7106                                 }
7107                                 for (i = size-1; i >= 0; i--) {
7108                                         if (same && !offr) {
7109                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7110                                         } else {
7111                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7112                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7113                                         }
7114                                 } // for i
7115                         } // if (offr)
7116                         break;
7117                         
7118                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7119                         /* works in-place/with offr as well */
7120                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7121                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7122                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7123
7124                         for (i = 1; i < size; i++)
7125                         {
7126                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7127                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7128                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7129                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7130                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7131                         } // for i
7132
7133                         if (sign)
7134                         {
7135                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7136                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7137                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7138                         } // if
7139                         break;
7140                         
7141                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7142                         /* works in-place/with offr as well */
7143                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7144                         for (i = 0; i < size-1; i++) {
7145                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7146                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7147                         } // for i
7148                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7149                         if (!sign) {
7150                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7151                         } else {
7152                                 emitSKPNC;
7153                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7154                         }
7155                         break;
7156                 
7157                 default:
7158                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7159                         shiftRight_Left2ResultLit (result, result, 1, sign);
7160                         return; /* prevent sign extending result again */
7161                         break;
7162                 } // switch
7163         } // if
7164
7165         addSign (result, size, sign);
7166 }
7167
7168 #if 0
7169 /*-----------------------------------------------------------------*/
7170 /* shiftL2Left2Result - shift left two bytes from left to result   */
7171 /*-----------------------------------------------------------------*/
7172 static void shiftL2Left2Result (operand *left, int offl,
7173                                                                 operand *result, int offr, int shCount)
7174 {
7175         FENTRY;
7176         
7177         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7178         
7179         if(pic14_sameRegs(AOP(result), AOP(left))) {
7180                 switch(shCount) {
7181                 case 0:
7182                         break;
7183                 case 1:
7184                 case 2:
7185                 case 3:
7186                         
7187                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7188                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7189                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7190                         
7191                         while(--shCount) {
7192                                 emitCLRC;
7193                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7194                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7195                         }
7196                         
7197                         break;
7198                 case 4:
7199                 case 5:
7200                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7201                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7202                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7203                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7204                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7205                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7206                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7207                         if(shCount >=5) {
7208                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7209                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7210                         }
7211                         break;
7212                 case 6:
7213                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7214                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7215                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7216                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7217                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7218                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7219                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7220                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7221                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7222                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7223                         break;
7224                 case 7:
7225                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7226                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7227                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7228                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7229                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7230                 }
7231                 
7232         } else {
7233                 switch(shCount) {
7234                 case 0:
7235                         break;
7236                 case 1:
7237                 case 2:
7238                 case 3:
7239                 /* note, use a mov/add for the shift since the mov has a
7240                         chance of getting optimized out */
7241                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7242                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7243                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7244                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7245                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7246                         
7247                         while(--shCount) {
7248                                 emitCLRC;
7249                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7250                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7251                         }
7252                         break;
7253                         
7254                 case 4:
7255                 case 5:
7256                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7257                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7258                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7259                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7260                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7261                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7262                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7263                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7264                         
7265                         
7266                         if(shCount == 5) {
7267                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7268                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7269                         }
7270                         break;
7271                 case 6:
7272                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7273                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7274                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7275                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7276                         
7277                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7278                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7279                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7280                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7281                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7282                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7283                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7284                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7285                         break;
7286                 case 7:
7287                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7288                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7289                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7290                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7291                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7292                 }
7293         }
7294         
7295 }
7296
7297 /*-----------------------------------------------------------------*/
7298 /* shiftR2Left2Result - shift right two bytes from left to result  */
7299 /*-----------------------------------------------------------------*/
7300 static void shiftR2Left2Result (operand *left, int offl,
7301                                                                 operand *result, int offr,
7302                                                                 int shCount, int sign)
7303 {
7304         int same=0;
7305         
7306         FENTRY;
7307         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7308         same = pic14_sameRegs(AOP(result), AOP(left));
7309         
7310         if(same && ((offl + MSB16) == offr)){
7311                 same=1;
7312                 /* don't crash result[offr] */
7313                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7314                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7315         }
7316         /* else {
7317         movLeft2Result(left,offl, result, offr);
7318         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7319         }
7320         */
7321         /* a:x >> shCount (x = lsb(result))*/
7322         /*
7323         if(sign)
7324         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7325         else {
7326         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7327         */
7328         switch(shCount) {
7329         case 0:
7330                 break;
7331         case 1:
7332         case 2:
7333         case 3:
7334                 if(sign)
7335                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7336                 else
7337                         emitCLRC;
7338                 
7339                 if(same) {
7340                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7341                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7342                 } else {
7343                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7344                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7345                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7346                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7347                 }
7348                 
7349                 while(--shCount) {
7350                         if(sign)
7351                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7352                         else
7353                                 emitCLRC;
7354                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7355                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7356                 }
7357                 break;
7358         case 4:
7359         case 5:
7360                 if(same) {
7361                         
7362                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7363                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7364                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7365                         
7366                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7367                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7368                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7369                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7370                 } else {
7371                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7372                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7373                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7374                         
7375                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7376                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7377                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7378                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7379                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7380                 }
7381                 
7382                 if(shCount >=5) {
7383                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7384                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7385                 }
7386                 
7387                 if(sign) {
7388                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7389                         emitpcode(POC_BTFSC, 
7390                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7391                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7392                 }
7393                 
7394                 break;
7395                 
7396         case 6:
7397                 if(same) {
7398                         
7399                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7400                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7401                         
7402                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7403                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7404                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7405                         emitpcode(POC_ANDLW,popGetLit(0x03));
7406                         if(sign) {
7407                                 emitpcode(POC_BTFSC, 
7408                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7409                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7410                         }
7411                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7412                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7413                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7414                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7415                 } else {
7416                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7417                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7418                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7419                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7420                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7421                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7422                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7423                         emitpcode(POC_ANDLW,popGetLit(0x03));
7424                         if(sign) {
7425                                 emitpcode(POC_BTFSC, 
7426                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7427                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7428                         }
7429                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7430                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7431                         
7432                         
7433                 }
7434                 
7435                 break;
7436         case 7:
7437                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7438                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7439                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7440                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7441                 if(sign) {
7442                         emitSKPNC;
7443                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7444                 } else 
7445                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7446   }
7447 }
7448
7449 /*-----------------------------------------------------------------*/
7450 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7451 /*-----------------------------------------------------------------*/
7452 static void shiftLLeftOrResult (operand *left, int offl,
7453                                                                 operand *result, int offr, int shCount)
7454 {
7455         FENTRY;
7456         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7457         
7458         /* shift left accumulator */
7459         AccLsh(left,offl,shCount);
7460         /* or with result */
7461         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7462         assert ( !"broken (modifies left, fails for left==result))" );
7463 }
7464
7465 /*-----------------------------------------------------------------*/
7466 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7467 /*-----------------------------------------------------------------*/
7468 static void shiftRLeftOrResult (operand *left, int offl,
7469                                                                 operand *result, int offr, int shCount)
7470 {
7471         FENTRY;
7472         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7473         
7474         /* shift right accumulator */
7475         AccRsh(left,offl,shCount);
7476         /* or with result */
7477         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7478         assert ( !"broken (modifies left, fails for left==result))" );
7479 }
7480
7481 /*-----------------------------------------------------------------*/
7482 /* genlshOne - left shift a one byte quantity by known count       */
7483 /*-----------------------------------------------------------------*/
7484 static void genlshOne (operand *result, operand *left, int shCount)
7485 {       
7486         FENTRY;
7487         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7488         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7489 }
7490
7491 /*-----------------------------------------------------------------*/
7492 /* genlshTwo - left shift two bytes by known amount != 0           */
7493 /*-----------------------------------------------------------------*/
7494 static void genlshTwo (operand *result,operand *left, int shCount)
7495 {
7496         int size;
7497         
7498         FENTRY;
7499         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7500         size = pic14_getDataSize(result);
7501         
7502         /* if shCount >= 8 */
7503         if (shCount >= 8) {
7504                 shCount -= 8 ;
7505                 
7506                 if (size > 1){
7507                         if (shCount)
7508                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7509                         else 
7510                                 movLeft2Result(left, LSB, result, MSB16);
7511                 }
7512                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7513         }
7514         
7515         /*  1 <= shCount <= 7 */
7516         else {  
7517                 if(size == 1)
7518                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7519                 else 
7520                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7521         }
7522 }
7523
7524 /*-----------------------------------------------------------------*/
7525 /* shiftLLong - shift left one long from left to result            */
7526 /* offl = LSB or MSB16                                             */
7527 /*-----------------------------------------------------------------*/
7528 static void shiftLLong (operand *left, operand *result, int offr )
7529 {
7530         char *l;
7531         int size = AOP_SIZE(result);
7532         
7533         FENTRY;
7534         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7535         if(size >= LSB+offr){
7536                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7537                 MOVA(l);
7538                 pic14_emitcode("add","a,acc");
7539                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7540                         size >= MSB16+offr && offr != LSB )
7541                         pic14_emitcode("xch","a,%s",
7542                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7543                 else      
7544                         aopPut(AOP(result),"a",LSB+offr);
7545         }
7546         
7547         if(size >= MSB16+offr){
7548                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7549                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7550                         MOVA(l);
7551                 }
7552                 pic14_emitcode("rlc","a");
7553                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7554                         size >= MSB24+offr && offr != LSB)
7555                         pic14_emitcode("xch","a,%s",
7556                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7557                 else      
7558                         aopPut(AOP(result),"a",MSB16+offr);
7559         }
7560         
7561         if(size >= MSB24+offr){
7562                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7563                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7564                         MOVA(l);
7565                 }
7566                 pic14_emitcode("rlc","a");
7567                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7568                         size >= MSB32+offr && offr != LSB )
7569                         pic14_emitcode("xch","a,%s",
7570                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7571                 else      
7572                         aopPut(AOP(result),"a",MSB24+offr);
7573         }
7574         
7575         if(size > MSB32+offr){
7576                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7577                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7578                         MOVA(l);  
7579                 }
7580                 pic14_emitcode("rlc","a");
7581                 aopPut(AOP(result),"a",MSB32+offr);
7582         }
7583         if(offr != LSB)
7584                 aopPut(AOP(result),zero,LSB);       
7585 }
7586
7587 /*-----------------------------------------------------------------*/
7588 /* genlshFour - shift four byte by a known amount != 0             */
7589 /*-----------------------------------------------------------------*/
7590 static void genlshFour (operand *result, operand *left, int shCount)
7591 {
7592         int size;
7593         
7594         FENTRY;
7595         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7596         size = AOP_SIZE(result);
7597         
7598         /* if shifting more that 3 bytes */
7599         if (shCount >= 24 ) {
7600                 shCount -= 24;
7601                 if (shCount)
7602                 /* lowest order of left goes to the highest
7603                 order of the destination */
7604                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7605                 else
7606                         movLeft2Result(left, LSB, result, MSB32);
7607                 aopPut(AOP(result),zero,LSB);
7608                 aopPut(AOP(result),zero,MSB16);
7609                 aopPut(AOP(result),zero,MSB32);
7610                 return;
7611         }
7612         
7613         /* more than two bytes */
7614         else if ( shCount >= 16 ) {
7615                 /* lower order two bytes goes to higher order two bytes */
7616                 shCount -= 16;
7617                 /* if some more remaining */
7618                 if (shCount)
7619                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7620                 else {
7621                         movLeft2Result(left, MSB16, result, MSB32);
7622                         movLeft2Result(left, LSB, result, MSB24);
7623                 }
7624                 aopPut(AOP(result),zero,MSB16);
7625                 aopPut(AOP(result),zero,LSB);
7626                 return;
7627         }    
7628         
7629         /* if more than 1 byte */
7630         else if ( shCount >= 8 ) {
7631                 /* lower order three bytes goes to higher order  three bytes */
7632                 shCount -= 8;
7633                 if(size == 2){
7634                         if(shCount)
7635                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7636                         else
7637                                 movLeft2Result(left, LSB, result, MSB16);
7638                 }
7639                 else{   /* size = 4 */
7640                         if(shCount == 0){
7641                                 movLeft2Result(left, MSB24, result, MSB32);
7642                                 movLeft2Result(left, MSB16, result, MSB24);
7643                                 movLeft2Result(left, LSB, result, MSB16);
7644                                 aopPut(AOP(result),zero,LSB);
7645                         }
7646                         else if(shCount == 1)
7647                                 shiftLLong(left, result, MSB16);
7648                         else{
7649                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7650                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7651                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7652                                 aopPut(AOP(result),zero,LSB);
7653                         }
7654                 }
7655         }
7656         
7657         /* 1 <= shCount <= 7 */
7658         else if(shCount <= 2){
7659                 shiftLLong(left, result, LSB);
7660                 if(shCount == 2)
7661                         shiftLLong(result, result, LSB);
7662         }
7663         /* 3 <= shCount <= 7, optimize */
7664         else{
7665                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7666                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7667                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7668         }
7669 }
7670 #endif
7671
7672 #if 0
7673 /*-----------------------------------------------------------------*/
7674 /* genLeftShiftLiteral - left shifting by known count              */
7675 /*-----------------------------------------------------------------*/
7676 static void genLeftShiftLiteral (operand *left,
7677                                                                  operand *right,
7678                                                                  operand *result,
7679                                                                  iCode *ic)
7680 {    
7681         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7682         //int size;
7683         
7684         FENTRY;
7685         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7686         freeAsmop(right,NULL,ic,TRUE);
7687         
7688         aopOp(left,ic,FALSE);
7689         aopOp(result,ic,FALSE);
7690
7691         size = getSize(operandType(result));
7692         
7693 #if VIEW_SIZE
7694         pic14_emitcode("; shift left ","result %d, left %d",size,
7695                 AOP_SIZE(left));
7696 #endif
7697         
7698         /* I suppose that the left size >= result size */
7699         if(shCount == 0){
7700                 while(size--){
7701                         movLeft2Result(left, size, result, size);
7702                 }
7703         }
7704         
7705         else if(shCount >= (size * 8))
7706                 while(size--)
7707                         aopPut(AOP(result),zero,size);
7708                 else{
7709                         switch (size) {
7710                         case 1:
7711                                 genlshOne (result,left,shCount);
7712                                 break;
7713                                 
7714                         case 2:
7715                         case 3:
7716                                 genlshTwo (result,left,shCount);
7717                                 break;
7718                                 
7719                         case 4:
7720                                 genlshFour (result,left,shCount);
7721                                 break;
7722                         }
7723                 }
7724                 freeAsmop(left,NULL,ic,TRUE);
7725                 freeAsmop(result,NULL,ic,TRUE);
7726 }
7727 #endif
7728
7729 /*-----------------------------------------------------------------*
7730 * genMultiAsm - repeat assembly instruction for size of register.
7731 * if endian == 1, then the high byte (i.e base address + size of 
7732 * register) is used first else the low byte is used first;
7733 *-----------------------------------------------------------------*/
7734 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7735 {
7736         
7737         int offset = 0;
7738         
7739         FENTRY;
7740         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7741         
7742         if(!reg)
7743                 return;
7744         
7745         if(!endian) {
7746                 endian = 1;
7747         } else {
7748                 endian = -1;
7749                 offset = size-1;
7750         }
7751         
7752         while(size--) {
7753                 emitpcode(poc,    popGet(AOP(reg),offset));
7754                 offset += endian;
7755         }
7756         
7757 }
7758 /*-----------------------------------------------------------------*/
7759 /* genLeftShift - generates code for left shifting                 */
7760 /*-----------------------------------------------------------------*/
7761 static void genLeftShift (iCode *ic)
7762 {
7763         operand *left,*right, *result;
7764         int size, offset;
7765         unsigned long lit = 0L;
7766         char *l;
7767         symbol *tlbl , *tlbl1;
7768         pCodeOp *pctemp;
7769         
7770         FENTRY;
7771         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7772         
7773         right = IC_RIGHT(ic);
7774         left  = IC_LEFT(ic);
7775         result = IC_RESULT(ic);
7776         
7777         aopOp(right,ic,FALSE);
7778         aopOp(left,ic,FALSE);
7779         aopOp(result,ic,FALSE);
7780         
7781         
7782         /* if the shift count is known then do it 
7783         as efficiently as possible */
7784         if (AOP_TYPE(right) == AOP_LIT) {
7785                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7786                 return ;
7787         }
7788         
7789         /* shift count is unknown then we have to form 
7790         a loop get the loop count in B : Note: we take
7791         only the lower order byte since shifting
7792         more that 32 bits make no sense anyway, ( the
7793         largest size of an object can be only 32 bits ) */  
7794         
7795         /* this code fails for RIGHT == RESULT */
7796         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7797         
7798         /* now move the left to the result if they are not the
7799         same */
7800         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7801                 AOP_SIZE(result) > 1) {
7802                 
7803                 size = AOP_SIZE(result);
7804                 offset=0;
7805                 while (size--) {
7806                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7807                         if (*l == '@' && (IS_AOP_PREG(result))) {
7808                                 
7809                                 pic14_emitcode("mov","a,%s",l);
7810                                 aopPut(AOP(result),"a",offset);
7811                         } else {
7812                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7813                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7814                                 //aopPut(AOP(result),l,offset);
7815                         }
7816                         offset++;
7817                 }
7818         }
7819         
7820         if(AOP_TYPE(left) == AOP_LIT)
7821                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7822
7823         size = AOP_SIZE(result);
7824         
7825         /* if it is only one byte then */
7826         if (size == 1) {
7827                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7828                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7829                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7830                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7831                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7832                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7833                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7834                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7835                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7836                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7837                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7838                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7839                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7840                 } else {
7841                         
7842                         tlbl = newiTempLabel(NULL);
7843                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7844                                 mov2w (AOP(left), 0);
7845                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7846                         }
7847                         
7848                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7849                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7850                         emitpLabel(tlbl->key);
7851                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7852                         emitpcode(POC_ADDLW,  popGetLit(1));
7853                         emitSKPC;
7854                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7855                 }
7856                 goto release ;
7857         }
7858         
7859         if (pic14_sameRegs(AOP(left),AOP(result))) {
7860                 
7861                 tlbl = newiTempLabel(NULL);
7862                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7863                 genMultiAsm(POC_RRF, result, size,1);
7864                 emitpLabel(tlbl->key);
7865                 genMultiAsm(POC_RLF, result, size,0);
7866                 emitpcode(POC_ADDLW,  popGetLit(1));
7867                 emitSKPC;
7868                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7869                 goto release;
7870         }
7871         
7872         //tlbl = newiTempLabel(NULL);
7873         //offset = 0 ;   
7874         //tlbl1 = newiTempLabel(NULL);
7875         
7876         //reAdjustPreg(AOP(result));    
7877         
7878         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7879         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7880         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7881         //MOVA(l);
7882         //pic14_emitcode("add","a,acc");         
7883         //aopPut(AOP(result),"a",offset++);
7884         //while (--size) {
7885         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7886         //  MOVA(l);
7887         //  pic14_emitcode("rlc","a");         
7888         //  aopPut(AOP(result),"a",offset++);
7889         //}
7890         //reAdjustPreg(AOP(result));
7891         
7892         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7893         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7894         
7895         
7896         tlbl = newiTempLabel(NULL);
7897         tlbl1= newiTempLabel(NULL);
7898         
7899         size = AOP_SIZE(result);
7900         offset = 1;
7901         
7902         pctemp = popGetTempReg();  /* grab a temporary working register. */
7903         
7904         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7905         
7906         /* offset should be 0, 1 or 3 */
7907         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7908         emitSKPNZ;
7909         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7910         
7911         emitpcode(POC_MOVWF, pctemp);
7912         
7913         
7914         emitpLabel(tlbl->key);
7915         
7916         emitCLRC;
7917         emitpcode(POC_RLF,  popGet(AOP(result),0));
7918         while(--size)
7919                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7920         
7921         emitpcode(POC_DECFSZ,  pctemp);
7922         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7923         emitpLabel(tlbl1->key);
7924         
7925         popReleaseTempReg(pctemp);
7926         
7927         
7928 release:
7929         freeAsmop (right,NULL,ic,TRUE);
7930         freeAsmop(left,NULL,ic,TRUE);
7931         freeAsmop(result,NULL,ic,TRUE);
7932 }
7933
7934 #if 0
7935 /*-----------------------------------------------------------------*/
7936 /* genrshOne - right shift a one byte quantity by known count      */
7937 /*-----------------------------------------------------------------*/
7938 static void genrshOne (operand *result, operand *left,
7939                                            int shCount, int sign)
7940 {
7941         FENTRY;
7942         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7943         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7944 }
7945
7946 /*-----------------------------------------------------------------*/
7947 /* genrshTwo - right shift two bytes by known amount != 0          */
7948 /*-----------------------------------------------------------------*/
7949 static void genrshTwo (operand *result,operand *left,
7950                                            int shCount, int sign)
7951 {
7952         FENTRY;
7953         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7954         /* if shCount >= 8 */
7955         if (shCount >= 8) {
7956                 shCount -= 8 ;
7957                 if (shCount)
7958                         shiftR1Left2Result(left, MSB16, result, LSB,
7959                         shCount, sign);
7960                 else
7961                         movLeft2Result(left, MSB16, result, LSB);
7962                 
7963                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7964                 
7965                 if(sign) {
7966                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7967                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7968                 }
7969         }
7970         
7971         /*  1 <= shCount <= 7 */
7972         else
7973                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7974 }
7975
7976 /*-----------------------------------------------------------------*/
7977 /* shiftRLong - shift right one long from left to result           */
7978 /* offl = LSB or MSB16                                             */
7979 /*-----------------------------------------------------------------*/
7980 static void shiftRLong (operand *left, int offl,
7981                                                 operand *result, int sign)
7982 {
7983         int size, same;
7984         
7985         FENTRY;
7986         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7987         
7988         size = AOP_SIZE(left);
7989         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7990         
7991         if (sign)
7992                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7993         else
7994                 emitCLRC;
7995
7996         assert (offl >= 0 && offl < size);
7997
7998         same = pic14_sameRegs (AOP(left), AOP(result));
7999
8000         /* perform the shift */
8001         while (size--)
8002         {
8003                 if (same && !offl) {
8004                         emitpcode (POC_RRF, popGet (AOP(result), size));
8005                 } else {
8006                         emitpcode (POC_RRFW, popGet (AOP(left), size));
8007                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
8008                 }
8009         } // while
8010
8011         addSign (result, AOP_SIZE(left) - offl, sign);
8012 }
8013
8014 /*-----------------------------------------------------------------*/
8015 /* genrshFour - shift four byte by a known amount != 0             */
8016 /*-----------------------------------------------------------------*/
8017 static void genrshFour (operand *result, operand *left,
8018                                                 int shCount, int sign)
8019 {
8020         FENTRY;
8021         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8022         /* if shifting more that 3 bytes */
8023         if(shCount >= 24 ) {
8024                 shCount -= 24;
8025                 if(shCount)
8026                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8027                 else
8028                         movLeft2Result(left, MSB32, result, LSB);
8029                 
8030                 addSign(result, MSB16, sign);
8031         }
8032         else if(shCount >= 16){
8033                 shCount -= 16;
8034                 if(shCount)
8035                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8036                 else{
8037                         movLeft2Result(left, MSB24, result, LSB);
8038                         movLeft2Result(left, MSB32, result, MSB16);
8039                 }
8040                 addSign(result, MSB24, sign);
8041         }
8042         else if(shCount >= 8){
8043                 shCount -= 8;
8044                 if(shCount == 1)
8045                         shiftRLong(left, MSB16, result, sign);
8046                 else if(shCount == 0){
8047                         movLeft2Result(left, MSB16, result, LSB);
8048                         movLeft2Result(left, MSB24, result, MSB16);
8049                         movLeft2Result(left, MSB32, result, MSB24);
8050                         addSign(result, MSB32, sign);
8051                 }
8052                 else{
8053                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8054                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8055                         /* the last shift is signed */
8056                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8057                         addSign(result, MSB32, sign);
8058                 }
8059         }
8060         else{   /* 1 <= shCount <= 7 */
8061                 if(shCount <= 2){
8062                         shiftRLong(left, LSB, result, sign);
8063                         if(shCount == 2)
8064                                 shiftRLong(result, LSB, result, sign);
8065                 }
8066                 else{
8067                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8068                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8069                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8070                 }
8071         }
8072 }
8073
8074 /*-----------------------------------------------------------------*/
8075 /* genRightShiftLiteral - right shifting by known count            */
8076 /*-----------------------------------------------------------------*/
8077 static void genRightShiftLiteral (operand *left,
8078                                                                   operand *right,
8079                                                                   operand *result,
8080                                                                   iCode *ic,
8081                                                                   int sign)
8082 {    
8083         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8084         int lsize,res_size;
8085         
8086         FENTRY;
8087         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8088         freeAsmop(right,NULL,ic,TRUE);
8089         
8090         aopOp(left,ic,FALSE);
8091         aopOp(result,ic,FALSE);
8092         
8093 #if VIEW_SIZE
8094         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8095                 AOP_SIZE(left));
8096 #endif
8097         
8098         lsize = pic14_getDataSize(left);
8099         res_size = pic14_getDataSize(result);
8100         /* test the LEFT size !!! */
8101         
8102         /* I suppose that the left size >= result size */
8103         if(shCount == 0){
8104                 while(res_size--)
8105                         movLeft2Result(left, res_size, result, res_size);
8106         }
8107         
8108         else if(shCount >= (lsize * 8)){
8109                 
8110                 if(res_size == 1) {
8111                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8112                         if(sign) {
8113                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8114                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8115                         }
8116                 } else {
8117                         
8118                         if(sign) {
8119                                 emitpcode(POC_MOVLW, popGetLit(0));
8120                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8121                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8122                                 while(res_size--)
8123                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8124                                 
8125                         } else {
8126                                 
8127                                 while(res_size--)
8128                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8129                         }
8130                 }
8131         } else {
8132                 
8133                 switch (res_size) {
8134                 case 1:
8135                         genrshOne (result,left,shCount,sign);
8136                         break;
8137                         
8138                 case 2:
8139                         genrshTwo (result,left,shCount,sign);
8140                         break;
8141                         
8142                 case 4:
8143                         genrshFour (result,left,shCount,sign);
8144                         break;
8145                 default :
8146                         break;
8147                 }
8148                 
8149         }
8150
8151         freeAsmop(left,NULL,ic,TRUE);
8152         freeAsmop(result,NULL,ic,TRUE);
8153 }
8154 #endif
8155
8156 /*-----------------------------------------------------------------*/
8157 /* genSignedRightShift - right shift of signed number              */
8158 /*-----------------------------------------------------------------*/
8159 static void genSignedRightShift (iCode *ic)
8160 {
8161         operand *right, *left, *result;
8162         int size, offset;
8163         //  char *l;
8164         symbol *tlbl, *tlbl1 ;
8165         pCodeOp *pctemp;
8166         
8167         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8168         
8169         /* we do it the hard way put the shift count in b
8170         and loop thru preserving the sign */
8171         FENTRY;
8172         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8173         
8174         right = IC_RIGHT(ic);
8175         left  = IC_LEFT(ic);
8176         result = IC_RESULT(ic);
8177         
8178         aopOp(right,ic,FALSE);  
8179         aopOp(left,ic,FALSE);
8180         aopOp(result,ic,FALSE);
8181         
8182         
8183         if ( AOP_TYPE(right) == AOP_LIT) {
8184                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8185                 //genRightShiftLiteral (left,right,result,ic,1);
8186                 return ;
8187         }
8188         /* shift count is unknown then we have to form 
8189         a loop get the loop count in B : Note: we take
8190         only the lower order byte since shifting
8191         more that 32 bits make no sense anyway, ( the
8192         largest size of an object can be only 32 bits ) */  
8193         
8194         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8195         //pic14_emitcode("inc","b");
8196         //freeAsmop (right,NULL,ic,TRUE);
8197         //aopOp(left,ic,FALSE);
8198         //aopOp(result,ic,FALSE);
8199         
8200         /* now move the left to the result if they are not the
8201         same */
8202         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8203                 AOP_SIZE(result) > 1) {
8204                 
8205                 size = AOP_SIZE(result);
8206                 offset=0;
8207                 while (size--) { 
8208                         /*
8209                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8210                         if (*l == '@' && IS_AOP_PREG(result)) {
8211                                 pic14_emitcode("mov","a,%s",l);
8212                                 aopPut(AOP(result),"a",offset);
8213                         } else
8214                         aopPut(AOP(result),l,offset);
8215                         */
8216                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8217                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8218                         
8219                         offset++;
8220                 }
8221         }
8222         
8223         /* mov the highest order bit to OVR */    
8224         tlbl = newiTempLabel(NULL);
8225         tlbl1= newiTempLabel(NULL);
8226         
8227         size = AOP_SIZE(result);
8228         offset = size - 1;
8229         
8230         pctemp = popGetTempReg();  /* grab a temporary working register. */
8231         
8232         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8233         
8234         /* offset should be 0, 1 or 3 */
8235         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8236         emitSKPNZ;
8237         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8238         
8239         emitpcode(POC_MOVWF, pctemp);
8240         
8241         
8242         emitpLabel(tlbl->key);
8243         
8244         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8245         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8246         
8247         while(--size) {
8248                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8249         }
8250         
8251         emitpcode(POC_DECFSZ,  pctemp);
8252         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8253         emitpLabel(tlbl1->key);
8254         
8255         popReleaseTempReg(pctemp);
8256 #if 0
8257         size = AOP_SIZE(result);
8258         offset = size - 1;
8259         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8260         pic14_emitcode("rlc","a");
8261         pic14_emitcode("mov","ov,c");
8262         /* if it is only one byte then */
8263         if (size == 1) {
8264                 l = aopGet(AOP(left),0,FALSE,FALSE);
8265                 MOVA(l);
8266                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8267                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8268                 pic14_emitcode("mov","c,ov");
8269                 pic14_emitcode("rrc","a");
8270                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8271                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8272                 aopPut(AOP(result),"a",0);
8273                 goto release ;
8274         }
8275         
8276         reAdjustPreg(AOP(result));
8277         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8278         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8279         pic14_emitcode("mov","c,ov");
8280         while (size--) {
8281                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8282                 MOVA(l);
8283                 pic14_emitcode("rrc","a");         
8284                 aopPut(AOP(result),"a",offset--);
8285         }
8286         reAdjustPreg(AOP(result));
8287         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8288         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8289         
8290 release:
8291 #endif
8292         
8293         freeAsmop(left,NULL,ic,TRUE);
8294         freeAsmop(result,NULL,ic,TRUE);
8295         freeAsmop(right,NULL,ic,TRUE);
8296 }
8297
8298 /*-----------------------------------------------------------------*/
8299 /* genRightShift - generate code for right shifting                */
8300 /*-----------------------------------------------------------------*/
8301 static void genRightShift (iCode *ic)
8302 {
8303         operand *right, *left, *result;
8304         sym_link *retype ;
8305         int size, offset;
8306         char *l;
8307         symbol *tlbl, *tlbl1 ;
8308         
8309         FENTRY;
8310         /* if signed then we do it the hard way preserve the
8311         sign bit moving it inwards */
8312         retype = getSpec(operandType(IC_RESULT(ic)));
8313         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8314         
8315         if (!SPEC_USIGN(retype)) {
8316                 genSignedRightShift (ic);
8317                 return ;
8318         }
8319         
8320         /* signed & unsigned types are treated the same : i.e. the
8321         signed is NOT propagated inwards : quoting from the
8322         ANSI - standard : "for E1 >> E2, is equivalent to division
8323         by 2**E2 if unsigned or if it has a non-negative value,
8324         otherwise the result is implementation defined ", MY definition
8325         is that the sign does not get propagated */
8326         
8327         right = IC_RIGHT(ic);
8328         left  = IC_LEFT(ic);
8329         result = IC_RESULT(ic);
8330         
8331         aopOp(right,ic,FALSE);
8332         aopOp(left,ic,FALSE);
8333         aopOp(result,ic,FALSE);
8334         
8335         /* if the shift count is known then do it 
8336         as efficiently as possible */
8337         if (AOP_TYPE(right) == AOP_LIT) {
8338                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 0);
8339                 //genRightShiftLiteral (left,right,result,ic, 0);
8340                 return ;
8341         }
8342         
8343         /* shift count is unknown then we have to form 
8344         a loop get the loop count in B : Note: we take
8345         only the lower order byte since shifting
8346         more that 32 bits make no sense anyway, ( the
8347         largest size of an object can be only 32 bits ) */  
8348         
8349         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8350         pic14_emitcode("inc","b");
8351         
8352         /* now move the left to the result if they are not the
8353         same */
8354         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8355                 AOP_SIZE(result) > 1) {
8356                 
8357                 size = AOP_SIZE(result);
8358                 offset=0;
8359                 while (size--) {
8360                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8361                         if (*l == '@' && IS_AOP_PREG(result)) {
8362                                 
8363                                 pic14_emitcode("mov","a,%s",l);
8364                                 aopPut(AOP(result),"a",offset);
8365                         } else
8366                                 aopPut(AOP(result),l,offset);
8367                         offset++;
8368                 }
8369         }
8370         
8371         tlbl = newiTempLabel(NULL);
8372         tlbl1= newiTempLabel(NULL);
8373         size = AOP_SIZE(result);
8374         offset = size - 1;
8375         
8376         /* if it is only one byte then */
8377         if (size == 1) {
8378                 
8379                 tlbl = newiTempLabel(NULL);
8380                 if (!pic14_sameRegs(AOP(left),AOP(result))) {
8381                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
8382                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
8383                 }
8384                 
8385                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
8386                 emitpcode(POC_RLF,    popGet(AOP(result),0));
8387                 emitpLabel(tlbl->key);
8388                 emitpcode(POC_RRF,    popGet(AOP(result),0));
8389                 emitpcode(POC_ADDLW,  popGetLit(1));
8390                 emitSKPC;
8391                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8392                 
8393                 goto release ;
8394         }
8395         
8396         reAdjustPreg(AOP(result));
8397         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8398         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8399         CLRC;
8400         while (size--) {
8401                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8402                 MOVA(l);
8403                 pic14_emitcode("rrc","a");         
8404                 aopPut(AOP(result),"a",offset--);
8405         }
8406         reAdjustPreg(AOP(result));
8407         
8408         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8409         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8410         
8411 release:
8412         freeAsmop(left,NULL,ic,TRUE);
8413         freeAsmop (right,NULL,ic,TRUE);
8414         freeAsmop(result,NULL,ic,TRUE);
8415 }
8416
8417 /*-----------------------------------------------------------------*/
8418 /* genUnpackBits - generates code for unpacking bits               */
8419 /*-----------------------------------------------------------------*/
8420 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype, iCode *ifx)
8421 {    
8422         int shCnt;
8423         int offset = 0;       /* result byte offset */
8424         int rsize;            /* result size */
8425         int rlen = 0;         /* remaining bitfield length */
8426         sym_link *etype;      /* bitfield type information */
8427         int blen;             /* bitfield length */
8428         int bstr;             /* bitfield starting bit within byte */
8429
8430         FENTRY;
8431         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8432         etype = getSpec(operandType(result));
8433         rsize = getSize (operandType (result));
8434         blen = SPEC_BLEN (etype);
8435         bstr = SPEC_BSTR (etype);
8436         
8437         /* single bit field case */
8438         if (blen == 1) {
8439                 if (ifx) { /* that is for an if statement */
8440                         pCodeOp *pcop;
8441                         resolvedIfx rIfx;
8442                         resolveIfx(&rIfx,ifx);
8443                         if (ptype == -1) /* direct */
8444                                 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8445                         else
8446                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8447                         emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8448                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8449                         ifx->generated=1;
8450                 } else {
8451                         pCodeOp *pcop;
8452                         int i;
8453                         assert (!pic14_sameRegs (AOP(result), AOP(left)));
8454                         for (i=0; i < AOP_SIZE(result); i++)
8455                                 emitpcode (POC_CLRF, popGet (AOP(result), i));
8456                         if (ptype == -1) /* direct */
8457                                 pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8458                         else
8459                                 pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8460                         emitpcode(POC_BTFSC,pcop);
8461                         emitpcode(POC_BSF,newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),0,0));
8462                 }
8463                 return;
8464         }
8465
8466         {
8467           static int has_warned=0;
8468           if (!has_warned)
8469           {
8470             fprintf (stderr, "%s: bitfields with more than 1 bit are probably broken...", __FUNCTION__);
8471             has_warned=1;
8472           }
8473         }
8474
8475         /* read the first byte  */
8476         switch (ptype) {
8477                 
8478         case POINTER:
8479         case IPOINTER:
8480 //              pic14_emitcode("mov","a,@%s",rname);
8481                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
8482                 break;
8483                 
8484         case PPOINTER:
8485                 pic14_emitcode("movx","a,@%s",rname);
8486                 break;
8487                 
8488         case FPOINTER:
8489                 pic14_emitcode("movx","a,@dptr");
8490                 break;
8491                 
8492         case CPOINTER:
8493                 pic14_emitcode("clr","a");
8494                 pic14_emitcode("movc","a","@a+dptr");
8495                 break;
8496                 
8497         case GPOINTER:
8498                 pic14_emitcode("lcall","__gptrget");
8499                 break;
8500         }
8501
8502         /* if we have bitdisplacement then it fits   */
8503         /* into this byte completely or if length is */
8504         /* less than a byte                          */
8505         if ((shCnt = SPEC_BSTR(etype)) || blen <= 8)  {
8506                 
8507                 /* shift right acc */
8508                 AccRsh(left,0,shCnt);
8509                 
8510                 pic14_emitcode("anl","a,#0x%02x",
8511                         ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8512                 aopPut(AOP(result),"a",offset);
8513                 return ;
8514         }
8515         
8516         /* bit field did not fit in a byte  */
8517         rlen = SPEC_BLEN(etype) - 8;
8518         aopPut(AOP(result),"a",offset++);
8519         
8520         while (1)  {
8521                 
8522                 switch (ptype) {
8523                 case POINTER:
8524                 case IPOINTER:
8525                         pic14_emitcode("inc","%s",rname);
8526                         pic14_emitcode("mov","a,@%s",rname);
8527                         break;
8528                         
8529                 case PPOINTER:
8530                         pic14_emitcode("inc","%s",rname);
8531                         pic14_emitcode("movx","a,@%s",rname);
8532                         break;
8533                         
8534                 case FPOINTER:
8535                         pic14_emitcode("inc","dptr");
8536                         pic14_emitcode("movx","a,@dptr");
8537                         break;
8538                         
8539                 case CPOINTER:
8540                         pic14_emitcode("clr","a");
8541                         pic14_emitcode("inc","dptr");
8542                         pic14_emitcode("movc","a","@a+dptr");
8543                         break;
8544                         
8545                 case GPOINTER:
8546                         pic14_emitcode("inc","dptr");
8547                         pic14_emitcode("lcall","__gptrget");
8548                         break;
8549                 }
8550                 
8551                 rlen -= 8;            
8552                 /* if we are done */
8553                 if ( rlen <= 0 )
8554                         break ;
8555                 
8556                 aopPut(AOP(result),"a",offset++);
8557                 
8558         }
8559         
8560         if (rlen) {
8561                 pic14_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8562                 aopPut(AOP(result),"a",offset);        
8563         }
8564         
8565         return ;
8566 }
8567
8568 #if 1
8569 /*-----------------------------------------------------------------*/
8570 /* genDataPointerGet - generates code when ptr offset is known     */
8571 /*-----------------------------------------------------------------*/
8572 static void genDataPointerGet (operand *left, 
8573         operand *result, 
8574         iCode *ic)
8575 {
8576         int size , offset = 0;
8577                 
8578         FENTRY;
8579         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8580         
8581         
8582         /* optimization - most of the time, left and result are the same
8583         * address, but different types. for the pic code, we could omit
8584         * the following
8585         */
8586         aopOp(result,ic,TRUE);
8587         
8588         if (pic14_sameRegs (AOP(left), AOP(result)))
8589                 return;
8590         
8591         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8592         
8593         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8594         
8595         size = AOP_SIZE(result);
8596         if (size > AOP_SIZE(left)) size = AOP_SIZE(left);
8597         
8598         while (size--) {
8599                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8600                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8601                 offset++;
8602         }
8603         
8604         freeAsmop(left,NULL,ic,TRUE);
8605         freeAsmop(result,NULL,ic,TRUE);
8606 }
8607 #endif
8608 /*-----------------------------------------------------------------*/
8609 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8610 /*-----------------------------------------------------------------*/
8611 static void genNearPointerGet (operand *left, 
8612                                                            operand *result, 
8613                                                            iCode *ic)
8614 {
8615         asmop *aop = NULL;
8616         sym_link *ltype = operandType(left);
8617         sym_link *rtype = operandType(result);
8618         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8619         int direct = 0;
8620
8621         FENTRY;
8622         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8623         
8624         
8625         aopOp(left,ic,FALSE);
8626         
8627         /* if left is rematerialisable and
8628         result is not bit variable type and
8629         the left is pointer to data space i.e
8630         lower 128 bytes of space */
8631         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8632                 !IS_BITVAR(retype)         &&
8633                 DCL_TYPE(ltype) == POINTER) {
8634                 genDataPointerGet (left,result,ic);
8635                 return ;
8636         }
8637         
8638         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8639         aopOp (result,ic,FALSE);
8640         
8641         /* Check if can access directly instead of via a pointer */
8642         if (PCOP(AOP(left))->type == PO_LITERAL && AOP_SIZE(result) == 1) {
8643                 direct = 1;
8644         }
8645
8646         /* If the pointer value is not in a the FSR then need to put it in */
8647         if (!AOP_INPREG(AOP(left)) && !direct) {
8648                 /* otherwise get a free pointer register */
8649                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8650                 if (PCOP(AOP(result))->type == PO_LITERAL) /* XXX: check me */ 
8651                         emitpcode(POC_MOVLW, popGet(AOP(left),0));
8652                 else
8653                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
8654                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
8655         }
8656         
8657         
8658 //      sym_link *etype;
8659         /* if bitfield then unpack the bits */
8660         if (IS_BITFIELD(retype)) 
8661                 genUnpackBits (result,left,"indf",direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8662         else {
8663                 /* we have can just get the values */
8664                 int size = AOP_SIZE(result);
8665                 int offset = 0 ;  
8666                 
8667                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8668                 
8669                 while(size--) {
8670                         if (direct)
8671                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8672                         else
8673                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8674                         if (AOP_TYPE(result) == AOP_LIT) {
8675                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8676                         } else {
8677                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8678                         }
8679                         if (size && !direct)
8680                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8681                         offset++;
8682                 }
8683         }
8684         
8685         /* now some housekeeping stuff */
8686         if (aop) {
8687                 /* we had to allocate for this iCode */
8688                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8689                 freeAsmop(NULL,aop,ic,TRUE);
8690         } else { 
8691                 /* we did not allocate which means left
8692                 already in a pointer register, then
8693                 if size > 0 && this could be used again
8694                 we have to point it back to where it 
8695                 belongs */
8696                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8697                 if (AOP_SIZE(result) > 1 &&
8698                         !OP_SYMBOL(left)->remat &&
8699                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8700                         ic->depth )) {
8701                         int size = AOP_SIZE(result) - 1;
8702                         while (size--)
8703                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8704                 }
8705         }
8706         
8707         /* done */
8708         freeAsmop(left,NULL,ic,TRUE);
8709         freeAsmop(result,NULL,ic,TRUE);
8710
8711 }
8712
8713 /*-----------------------------------------------------------------*/
8714 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8715 /*-----------------------------------------------------------------*/
8716 static void genPagedPointerGet (operand *left, 
8717                                                                 operand *result, 
8718                                                                 iCode *ic)
8719 {
8720         asmop *aop = NULL;
8721         regs *preg = NULL ;
8722         char *rname ;
8723         sym_link *rtype, *retype;    
8724         
8725         FENTRY;
8726         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8727         
8728         rtype = operandType(result);
8729         retype= getSpec(rtype);
8730         
8731         aopOp(left,ic,FALSE);
8732         
8733         /* if the value is already in a pointer register
8734         then don't need anything more */
8735         if (!AOP_INPREG(AOP(left))) {
8736                 /* otherwise get a free pointer register */
8737                 aop = newAsmop(0);
8738                 preg = getFreePtr(ic,&aop,FALSE);
8739                 pic14_emitcode("mov","%s,%s",
8740                         preg->name,
8741                         aopGet(AOP(left),0,FALSE,TRUE));
8742                 rname = preg->name ;
8743         } else
8744                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8745         
8746         freeAsmop(left,NULL,ic,TRUE);
8747         aopOp (result,ic,FALSE);
8748         
8749         /* if bitfield then unpack the bits */
8750         if (IS_BITFIELD(retype)) 
8751                 genUnpackBits (result,left,rname,PPOINTER,0);
8752         else {
8753                 /* we have can just get the values */
8754                 int size = AOP_SIZE(result);
8755                 int offset = 0 ;  
8756                 
8757                 while (size--) {
8758                         
8759                         pic14_emitcode("movx","a,@%s",rname);
8760                         aopPut(AOP(result),"a",offset);
8761                         
8762                         offset++ ;
8763                         
8764                         if (size)
8765                                 pic14_emitcode("inc","%s",rname);
8766                 }
8767         }
8768         
8769         /* now some housekeeping stuff */
8770         if (aop) {
8771                 /* we had to allocate for this iCode */
8772                 freeAsmop(NULL,aop,ic,TRUE);
8773         } else { 
8774         /* we did not allocate which means left
8775         already in a pointer register, then
8776         if size > 0 && this could be used again
8777         we have to point it back to where it 
8778                 belongs */
8779                 if (AOP_SIZE(result) > 1 &&
8780                         !OP_SYMBOL(left)->remat &&
8781                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8782                         ic->depth )) {
8783                         int size = AOP_SIZE(result) - 1;
8784                         while (size--)
8785                                 pic14_emitcode("dec","%s",rname);
8786                 }
8787         }
8788         
8789         /* done */
8790         freeAsmop(result,NULL,ic,TRUE);
8791         
8792         
8793 }
8794
8795 /*-----------------------------------------------------------------*/
8796 /* genFarPointerGet - gget value from far space                    */
8797 /*-----------------------------------------------------------------*/
8798 static void genFarPointerGet (operand *left,
8799                                                           operand *result, iCode *ic)
8800 {
8801         int size, offset ;
8802         sym_link *retype = getSpec(operandType(result));
8803         
8804         FENTRY;
8805         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8806         
8807         aopOp(left,ic,FALSE);
8808         
8809         /* if the operand is already in dptr 
8810         then we do nothing else we move the value to dptr */
8811         if (AOP_TYPE(left) != AOP_STR) {
8812                 /* if this is remateriazable */
8813                 if (AOP_TYPE(left) == AOP_IMMD)
8814                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8815                 else { /* we need to get it byte by byte */
8816                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8817                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8818                         if (options.model == MODEL_FLAT24)
8819                         {
8820                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8821                         }
8822                 }
8823         }
8824         /* so dptr know contains the address */
8825         freeAsmop(left,NULL,ic,TRUE);
8826         aopOp(result,ic,FALSE);
8827         
8828         /* if bit then unpack */
8829         if (IS_BITFIELD(retype)) 
8830                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8831         else {
8832                 size = AOP_SIZE(result);
8833                 offset = 0 ;
8834                 
8835                 while (size--) {
8836                         pic14_emitcode("movx","a,@dptr");
8837                         aopPut(AOP(result),"a",offset++);
8838                         if (size)
8839                                 pic14_emitcode("inc","dptr");
8840                 }
8841         }
8842         
8843         freeAsmop(result,NULL,ic,TRUE);
8844 }
8845 #if 0
8846 /*-----------------------------------------------------------------*/
8847 /* genCodePointerGet - get value from code space                  */
8848 /*-----------------------------------------------------------------*/
8849 static void genCodePointerGet (operand *left,
8850                                                            operand *result, iCode *ic)
8851 {
8852         int size, offset ;
8853         sym_link *retype = getSpec(operandType(result));
8854         
8855         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8856         
8857         aopOp(left,ic,FALSE);
8858         
8859         /* if the operand is already in dptr 
8860         then we do nothing else we move the value to dptr */
8861         if (AOP_TYPE(left) != AOP_STR) {
8862                 /* if this is remateriazable */
8863                 if (AOP_TYPE(left) == AOP_IMMD)
8864                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8865                 else { /* we need to get it byte by byte */
8866                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8867                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8868                         if (options.model == MODEL_FLAT24)
8869                         {
8870                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8871                         }
8872                 }
8873         }
8874         /* so dptr know contains the address */
8875         freeAsmop(left,NULL,ic,TRUE);
8876         aopOp(result,ic,FALSE);
8877         
8878         /* if bit then unpack */
8879         if (IS_BITFIELD(retype)) 
8880                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8881         else {
8882                 size = AOP_SIZE(result);
8883                 offset = 0 ;
8884                 
8885                 while (size--) {
8886                         pic14_emitcode("clr","a");
8887                         pic14_emitcode("movc","a,@a+dptr");
8888                         aopPut(AOP(result),"a",offset++);
8889                         if (size)
8890                                 pic14_emitcode("inc","dptr");
8891                 }
8892         }
8893         
8894         freeAsmop(result,NULL,ic,TRUE);
8895 }
8896 #endif
8897 /*-----------------------------------------------------------------*/
8898 /* genGenPointerGet - gget value from generic pointer space        */
8899 /*-----------------------------------------------------------------*/
8900 static void genGenPointerGet (operand *left,
8901                                                           operand *result, iCode *ic)
8902 {
8903         int size, offset ;
8904         sym_link *retype = getSpec(operandType(result));
8905         
8906         FENTRY;
8907         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8908         aopOp(left,ic,FALSE);
8909         aopOp(result,ic,FALSE);
8910         
8911         
8912         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8913         
8914         /* if the operand is already in dptr 
8915         then we do nothing else we move the value to dptr */
8916         //  if (AOP_TYPE(left) != AOP_STR) {
8917         /* if this is remateriazable */
8918         if (AOP_TYPE(left) == AOP_IMMD) {
8919                 pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8920                 pic14_emitcode("mov","b,#%d",pointerCode(retype));
8921         }
8922         else { /* we need to get it byte by byte */
8923                 
8924                 emitpcode(POC_MOVFW,popGet(AOP(left),0));
8925                 emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
8926                 
8927                 size = AOP_SIZE(result);
8928                 offset = 0 ;
8929                 
8930                 while(size--) {
8931                         emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8932                         emitpcode(POC_MOVWF,popGet(AOP(result),offset++));
8933                         if(size)
8934                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8935                 }
8936                 goto release;
8937         }
8938         //}
8939         /* so dptr know contains the address */
8940         
8941         /* if bit then unpack */
8942         //if (IS_BITFIELD(retype)) 
8943         //  genUnpackBits(result,"dptr",GPOINTER);
8944         
8945 release:
8946         freeAsmop(left,NULL,ic,TRUE);
8947         freeAsmop(result,NULL,ic,TRUE);
8948         
8949 }
8950
8951 /*-----------------------------------------------------------------*/
8952 /* genConstPointerGet - get value from const generic pointer space */
8953 /*-----------------------------------------------------------------*/
8954 static void genConstPointerGet (operand *left,
8955                                                                 operand *result, iCode *ic)
8956 {
8957         //sym_link *retype = getSpec(operandType(result));
8958         symbol *albl, *blbl;//, *clbl;
8959         PIC_OPCODE poc;
8960         int i, size, lit;
8961         pCodeOp *pcop;
8962         
8963         FENTRY;
8964         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8965         aopOp(left,ic,FALSE);
8966         aopOp(result,ic,FALSE);
8967         
8968         size = AOP_SIZE(result);
8969         
8970         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8971         
8972         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
8973
8974         lit = aop_isLitLike (AOP(left));
8975         poc = lit ? POC_MOVLW : POC_MOVFW;
8976
8977         if (lit)
8978         {
8979                 for (i = 0; i < size; i++)
8980                 {
8981                         albl = newiTempLabel(NULL);
8982                         blbl = newiTempLabel(NULL);
8983                         
8984                         emitpcode(POC_CALL,popGetLabel(albl->key));
8985                         pcop = popGetLabel(blbl->key);
8986                         emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
8987                         emitpcode(POC_GOTO,pcop);
8988                         
8989                         emitpLabel(albl->key);
8990                         emitpcode(poc,popGetAddr(AOP(left),1,i));
8991                         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
8992                         emitpcode(poc,popGetAddr(AOP(left),0,i));
8993                         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
8994                 
8995                         emitpLabel(blbl->key);
8996                         emitpcode(POC_MOVWF,popGet(AOP(result),i));
8997                 } // for
8998         } else {
8999                 albl = newiTempLabel(NULL);
9000                 blbl = newiTempLabel(NULL);
9001                 //clbl = newiTempLabel(NULL);
9002
9003                 emitpcode (POC_GOTO, popGetLabel (blbl->key));
9004                 
9005                 emitpLabel(albl->key);
9006                 emitpcode(poc,popGet(AOP(left),1));
9007                 emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
9008                 emitpcode(poc,popGet(AOP(left),0));
9009                 emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
9010                 
9011                 emitpLabel(blbl->key);
9012                 
9013                 for (i = 0; i < size; i++)
9014                 {
9015                         emitpcode(POC_CALL,popGetLabel(albl->key));
9016                         /* the next two instructions (plus clbl) might be useless... */
9017                         //pcop = popGetLabel(clbl->key);
9018                         //emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
9019                         //emitpcode(POC_GOTO,pcop);
9020                         //emitpLabel(clbl->key);
9021
9022                         if (i+1 < size) {
9023                                 emitpcode (POC_INCF, popGet (AOP(left), 0));
9024                                 emitSKPNZ;
9025                                 emitpcode (POC_INCF, popGet (AOP(left), 1));
9026                         }
9027                         emitpcode(POC_MOVWF,popGet(AOP(result),i));
9028                 } // for
9029                 if (size > 1) {
9030                         /* restore left's value */
9031                         emitpcode (POC_MOVLW, popGetLit (size-1));
9032                         emitpcode (POC_SUBWF, popGet (AOP(left), 0));
9033                         emitSKPC;
9034                         emitpcode (POC_DECF, popGet (AOP(left), 1));
9035                 } // if
9036         } // if (lit)
9037         
9038         freeAsmop(left,NULL,ic,TRUE);
9039         freeAsmop(result,NULL,ic,TRUE);
9040         
9041 }
9042 /*-----------------------------------------------------------------*/
9043 /* genPointerGet - generate code for pointer get                   */
9044 /*-----------------------------------------------------------------*/
9045 static void genPointerGet (iCode *ic)
9046 {
9047         operand *left, *result ;
9048         sym_link *type, *etype;
9049         int p_type = -1;
9050         
9051         FENTRY;
9052         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9053         
9054         left = IC_LEFT(ic);
9055         result = IC_RESULT(ic) ;
9056         
9057         /* depending on the type of pointer we need to
9058         move it to the correct pointer register */
9059         type = operandType(left);
9060         etype = getSpec(type);
9061         
9062         if (IS_PTR_CONST(type))
9063                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9064         
9065         /* if left is of type of pointer then it is simple */
9066         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9067                 p_type = DCL_TYPE(type);
9068         else {
9069                 /* we have to go by the storage class */
9070                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9071                 
9072                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9073                 
9074                 if (SPEC_OCLS(etype)->codesp ) {
9075                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9076                         //p_type = CPOINTER ; 
9077                 }
9078                 else
9079                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9080                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9081                         /*p_type = FPOINTER ;*/ 
9082                         else
9083                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9084                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9085                                 /*        p_type = PPOINTER; */
9086                                 else
9087                                         if (SPEC_OCLS(etype) == idata )
9088                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9089                                         /*      p_type = IPOINTER; */
9090                                         else
9091                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9092                                         /*      p_type = POINTER ; */
9093         }
9094         
9095         /* now that we have the pointer type we assign
9096         the pointer values */
9097         switch (p_type) {
9098                 
9099         case POINTER: 
9100         case IPOINTER:
9101                 genNearPointerGet (left,result,ic);
9102                 break;
9103                 
9104         case PPOINTER:
9105                 genPagedPointerGet(left,result,ic);
9106                 break;
9107                 
9108         case FPOINTER:
9109                 genFarPointerGet (left,result,ic);
9110                 break;
9111                 
9112         case CPOINTER:
9113                 genConstPointerGet (left,result,ic);
9114                 //pic14_emitcodePointerGet (left,result,ic);
9115                 break;
9116                 
9117         case GPOINTER:
9118                 if (IS_CODEPTR(type) || IS_PTR_CONST(type) || SPEC_CONST(etype))
9119                         genConstPointerGet (left,result,ic);
9120                 else
9121                         genGenPointerGet (left,result,ic);
9122                 break;
9123         default:
9124                 assert ( !"unhandled pointer type" );
9125                 break;
9126         }
9127         
9128 }
9129
9130 /*-----------------------------------------------------------------*/
9131 /* emitPtrByteGet - for legacy 8051 emits code to get a byte into  */
9132 /* A through a pointer register (R0, R1, or DPTR). The original    */
9133 /* value of A can be preserved in B.                               */
9134 /* PIC has to use INDF register.                                   */
9135 /*-----------------------------------------------------------------*/
9136 static void
9137 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9138 {
9139     FENTRY;
9140     switch (p_type)
9141     {
9142     case IPOINTER:
9143     case POINTER:
9144                 if (preserveAinB)
9145                         pic14_emitcode ("mov", "b,a");
9146 //              pic14_emitcode ("mov", "a,@%s", rname);
9147                 emitpcode(POC_MOVFW, popCopyReg(&pc_indf));
9148                 break;
9149                 
9150     case PPOINTER:
9151                 if (preserveAinB)
9152                         pic14_emitcode ("mov", "b,a");
9153                 pic14_emitcode ("movx", "a,@%s", rname);
9154                 break;
9155                 
9156     case FPOINTER:
9157                 if (preserveAinB)
9158                         pic14_emitcode ("mov", "b,a");
9159                 pic14_emitcode ("movx", "a,@dptr");
9160                 break;
9161                 
9162     case CPOINTER:
9163                 if (preserveAinB)
9164                         pic14_emitcode ("mov", "b,a");
9165                 pic14_emitcode ("clr", "a");
9166                 pic14_emitcode ("movc", "a,@a+dptr");
9167                 break;
9168                 
9169     case GPOINTER:
9170                 if (preserveAinB)
9171         {
9172                         pic14_emitcode ("push", "b");
9173                         pic14_emitcode ("push", "acc");
9174         }
9175                 pic14_emitcode ("lcall", "__gptrget");
9176                 if (preserveAinB)
9177                         pic14_emitcode ("pop", "b");
9178                 break;
9179     }
9180 }
9181
9182 /*-----------------------------------------------------------------*/
9183 /* emitPtrByteSet - emits code to set a byte from src through a    */
9184 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
9185 /*-----------------------------------------------------------------*/
9186 static void
9187 emitPtrByteSet (char *rname, int p_type, char *src)
9188 {
9189     FENTRY;
9190     switch (p_type)
9191     {
9192     case IPOINTER:
9193     case POINTER:
9194                 if (*src=='@')
9195         {
9196                         MOVA (src);
9197                         pic14_emitcode ("mov", "@%s,a", rname);
9198         }
9199                 else
9200 //                      pic14_emitcode ("mov", "@%s,%s", rname, src);
9201                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9202                 break;
9203                 
9204     case PPOINTER:
9205                 MOVA (src);
9206                 pic14_emitcode ("movx", "@%s,a", rname);
9207                 break;
9208                 
9209     case FPOINTER:
9210                 MOVA (src);
9211                 pic14_emitcode ("movx", "@dptr,a");
9212                 break;
9213                 
9214     case GPOINTER:
9215                 MOVA (src);
9216                 pic14_emitcode ("lcall", "__gptrput");
9217                 break;
9218     }
9219 }
9220
9221 /*-----------------------------------------------------------------*/
9222 /* genPackBits - generates code for packed bit storage             */
9223 /*-----------------------------------------------------------------*/
9224 static void genPackBits(sym_link *etype,operand *result,operand *right,char *rname,int p_type)
9225 {
9226         int offset = 0;       /* source byte offset */
9227         int rlen = 0;         /* remaining bitfield length */
9228         int blen;             /* bitfield length */
9229         int bstr;             /* bitfield starting bit within byte */
9230         int litval;           /* source literal value (if AOP_LIT) */
9231         unsigned char mask;   /* bitmask within current byte */
9232
9233         FENTRY;
9234         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9235         
9236         blen = SPEC_BLEN (etype);
9237         bstr = SPEC_BSTR (etype);
9238         
9239         /* If the bitfield length is less than a byte */
9240         if (blen < 8)
9241     {
9242                 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9243                         (unsigned char) (0xFF >> (8 - bstr)));
9244                 
9245                 if (AOP_TYPE (right) == AOP_LIT)
9246         {
9247                         /* Case with a bitfield length <8 and literal source
9248                         */
9249                         int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9250                         if (blen == 1) {
9251                                 if (p_type == -1) {
9252                                         pCodeOp *pcop;
9253                                         if (AOP(result)->type == AOP_PCODE)
9254                                                 pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9255                                         else
9256                                                 pcop = popGet(AOP(result),0);
9257                                         emitpcode(lit?POC_BSF:POC_BCF,pcop);
9258                                 } else {
9259                                         emitpcode(lit?POC_BSF:POC_BCF,popCopyReg(&pc_indf));
9260                                 }
9261                                 return;
9262                         } else {
9263                                 litval = lit << bstr;
9264                                 litval &= (~mask) & 0xff;
9265                                 if (p_type == -1)
9266                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9267                                 else
9268                                         emitPtrByteGet (rname, p_type, FALSE);
9269                                 if ((mask|litval)!=0xff)
9270                                         emitpcode(POC_ANDLW,popGetLit(mask));
9271                                 if (litval)
9272                                         emitpcode(POC_IORLW,popGetLit(litval));
9273                         }
9274         }
9275                 else
9276         {
9277                         if (blen==1) {
9278                                 if (p_type == -1) {
9279                                         /* 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 */
9280                                         emitpcode(POC_RRFW,popGet(AOP(right),0));
9281                                         emitSKPC;
9282                                         emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9283                                         emitSKPNC;
9284                                         emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9285                                         return;
9286                                 } else if (p_type!=GPOINTER) {
9287                                         /* Case with a bitfield length == 1 and no generic pointer
9288                                         */
9289                                         if (AOP_TYPE (right) == AOP_CRY)
9290                                                 pic14_emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9291                                         else
9292                                         {
9293                                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9294                                                 pic14_emitcode ("rrc","a");
9295                                         }
9296                                         emitPtrByteGet (rname, p_type, FALSE);
9297                                         pic14_emitcode ("mov","acc.%d,c",bstr);
9298                                 }
9299             }
9300                         else
9301             {
9302                                 //bool pushedB;
9303                                 /* Case with a bitfield length < 8 and arbitrary source
9304                                 */
9305                                 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9306                                 /* shift and mask source value */
9307                                 AccLsh (right,0,bstr);
9308                                 pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9309                                 emitpcode(POC_ANDLW, popGetLit((~mask) & 0xff));
9310                                 
9311                                 //pushedB = pushB ();
9312                                 if (p_type == -1)
9313                                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9314                                 else
9315                                         emitPtrByteGet (rname, p_type, TRUE);
9316                                 
9317                                 pic14_emitcode ("anl", "a,#0x%02x", mask);
9318                                 pic14_emitcode ("orl", "a,b");
9319                                 emitpcode(POC_ANDLW,popGetLit(mask));
9320                                 emitpcode(POC_IORFW,popGet(AOP(right),0));
9321                                 if (p_type == GPOINTER)
9322                                         pic14_emitcode ("pop", "b");
9323                                 
9324                                 //popB (pushedB);
9325                         }
9326         }
9327                 
9328                 if (p_type == -1)
9329                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9330                 else
9331                         emitPtrByteSet (rname, p_type, "a");
9332                 return;
9333     }
9334         
9335         /* Bit length is greater than 7 bits. In this case, copy  */
9336         /* all except the partial byte at the end                 */
9337         for (rlen=blen;rlen>=8;rlen-=8)
9338     {
9339                 emitPtrByteSet (rname, p_type,
9340                         aopGet (AOP (right), offset++, FALSE, TRUE) );
9341                 if (rlen>8)
9342                         pic14_emitcode ("inc", "%s", rname);
9343     }
9344         
9345         /* If there was a partial byte at the end */
9346         if (rlen)
9347     {
9348                 mask = (((unsigned char) -1 << rlen) & 0xff);
9349                 
9350                 if (AOP_TYPE (right) == AOP_LIT)
9351         {
9352                 /* Case with partial byte and literal source
9353                         */
9354                         litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9355                         litval >>= (blen-rlen);
9356                         litval &= (~mask) & 0xff;
9357                         emitPtrByteGet (rname, p_type, FALSE);
9358                         if ((mask|litval)!=0xff)
9359                                 pic14_emitcode ("anl","a,#0x%02x", mask);
9360                         if (litval)
9361                                 pic14_emitcode ("orl","a,#0x%02x", litval);
9362         }
9363                 else
9364         {
9365                         //bool pushedB;
9366                         /* Case with partial byte and arbitrary source
9367                         */
9368                         MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9369                         pic14_emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9370                         
9371                         //pushedB = pushB ();
9372                         /* transfer A to B and get next byte */
9373                         emitPtrByteGet (rname, p_type, TRUE);
9374                         
9375                         pic14_emitcode ("anl", "a,#0x%02x", mask);
9376                         pic14_emitcode ("orl", "a,b");
9377                         if (p_type == GPOINTER)
9378                                 pic14_emitcode ("pop", "b");
9379                         
9380                         //popB (pushedB);
9381         }
9382                 emitPtrByteSet (rname, p_type, "a");
9383     }
9384         
9385 }
9386
9387 /*-----------------------------------------------------------------*/
9388 /* SetIrp - Set IRP bit                                            */
9389 /*-----------------------------------------------------------------*/
9390 void SetIrp(operand *result) {
9391         FENTRY;
9392         if (AOP_TYPE(result) == AOP_LIT) {
9393                 unsigned lit = (unsigned)operandLitValue(result);
9394                 emitpcode((lit&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9395         } else {
9396                 if (PCOP(AOP(result))->type == PO_LITERAL) {
9397                         int addrs = PCOL(AOP(result))->lit;
9398                         emitpcode((addrs&0x100)?POC_BSF:POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9399                 } else {
9400                         emitpcode(POC_BCF, popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT)); /* always ensure this is clear as it may have previouly been set */
9401                         if(AOP_SIZE(result) > 1) {
9402                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
9403                                 emitpcode(POC_BSF,  popCopyGPR2Bit(PCOP(&pc_status),PIC_IRP_BIT));
9404                         }
9405                 }
9406         }
9407 }
9408
9409 /*-----------------------------------------------------------------*/
9410 /* genDataPointerSet - remat pointer to data space                 */
9411 /*-----------------------------------------------------------------*/
9412 static void genDataPointerSet(operand *right,
9413         operand *result,
9414         iCode *ic)
9415 {
9416         int size, offset = 0 ;
9417         
9418         FENTRY;
9419         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9420         aopOp(right,ic,FALSE);
9421         aopOp(result,ic,FALSE);
9422         
9423         size = AOP_SIZE(right);
9424         /*
9425         if ( AOP_TYPE(result) == AOP_PCODE) {
9426         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9427         AOP(result)->aopu.pcop->name,
9428         PCOI(AOP(result)->aopu.pcop)->offset);
9429         }
9430         */
9431         
9432         // tsd, was l+1 - the underline `_' prefix was being stripped
9433         while (size--) {
9434                 emitpComment ("%s:%u: size=%i, offset=%i", __FILE__,__LINE__, size, offset);
9435                 
9436                 if (AOP_TYPE(right) == AOP_LIT) {
9437                         unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9438                         lit = lit >> (8*offset);
9439                         if(lit&0xff) {
9440                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9441                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9442                         } else {
9443                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9444                         }
9445                 } else {
9446                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9447                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9448                 }
9449                 
9450                 offset++;
9451         }
9452         
9453         freeAsmop(right,NULL,ic,TRUE);
9454         freeAsmop(result,NULL,ic,TRUE);
9455 }
9456
9457 /*-----------------------------------------------------------------*/
9458 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9459 /*-----------------------------------------------------------------*/
9460 static void genNearPointerSet (operand *right,
9461                                                            operand *result, 
9462                                                            iCode *ic)
9463 {
9464         asmop *aop = NULL;
9465         sym_link *ptype = operandType(result);
9466         sym_link *retype = getSpec(operandType(right));
9467         sym_link *letype = getSpec(ptype);
9468         int direct = 0;
9469         
9470         
9471         FENTRY;
9472         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9473         aopOp(result,ic,FALSE);
9474         
9475         
9476         /* if the result is rematerializable &
9477         in data space & not a bit variable */
9478         //if (AOP_TYPE(result) == AOP_IMMD &&
9479         if (AOP_TYPE(result) == AOP_PCODE &&
9480                 DCL_TYPE(ptype) == POINTER   &&
9481                 !IS_BITVAR (retype) &&
9482                 !IS_BITVAR (letype)) {
9483                 genDataPointerSet (right,result,ic);
9484                 freeAsmop(result,NULL,ic,TRUE);
9485                 return;
9486         }
9487
9488         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9489         aopOp(right,ic,FALSE);
9490         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9491         
9492         /* Check if can access directly instead of via a pointer */
9493         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9494                 direct = 1;
9495         }
9496
9497         /* If the pointer value is not in a the FSR then need to put it in */
9498         if (!AOP_INPREG(AOP(result)) && !direct) {
9499                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9500                 if (PCOP(AOP(result))->type == PO_LITERAL) 
9501                         emitpcode(POC_MOVLW, popGet(AOP(result),0));
9502                 else
9503                         emitpcode(POC_MOVFW, popGet(AOP(result),0));
9504                 emitpcode(POC_MOVWF, popCopyReg(&pc_fsr));
9505         }
9506
9507         /* Must set/reset IRP bit for use with FSR. */
9508         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9509         if (!direct)
9510                 SetIrp(result);
9511
9512         /* if bitfield then unpack the bits */
9513         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9514                 genPackBits ((IS_BITFIELD (retype) ? retype : letype), result, right, "indf", direct?-1:POINTER);
9515         } else {
9516                 /* we have can just get the values */
9517                 int size = AOP_SIZE(right);
9518                 int offset = 0 ;    
9519                 
9520                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9521                 while (size--) {
9522                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9523                         if (*l == '@' ) {
9524                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9525                         } else {
9526                                 if (AOP_TYPE(right) == AOP_LIT) {
9527                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9528                                 } else {
9529                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9530                                 }
9531                                 if (direct)
9532                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9533                                 else
9534                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9535                         }
9536                         if (size && !direct)
9537                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9538                         offset++;
9539                 }
9540         }
9541         
9542         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9543         /* now some housekeeping stuff */
9544         if (aop) {
9545                 /* we had to allocate for this iCode */
9546                 freeAsmop(NULL,aop,ic,TRUE);
9547         } else { 
9548                 /* we did not allocate which means left
9549                 already in a pointer register, then
9550                 if size > 0 && this could be used again
9551                 we have to point it back to where it 
9552                 belongs */
9553                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9554                 if (AOP_SIZE(right) > 1 &&
9555                         !OP_SYMBOL(result)->remat &&
9556                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9557                         ic->depth )) {
9558                         int size = AOP_SIZE(right) - 1;
9559                         while (size--)
9560                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9561                 }
9562         }
9563         
9564         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9565         /* done */
9566
9567         freeAsmop(right,NULL,ic,TRUE);
9568         freeAsmop(result,NULL,ic,TRUE);
9569 }
9570
9571 /*-----------------------------------------------------------------*/
9572 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9573 /*-----------------------------------------------------------------*/
9574 static void genPagedPointerSet (operand *right,
9575                                                                 operand *result, 
9576                                                                 iCode *ic)
9577 {
9578         asmop *aop = NULL;
9579         regs *preg = NULL ;
9580         char *rname , *l;
9581         sym_link *retype;
9582         
9583         FENTRY;
9584         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9585         
9586         retype= getSpec(operandType(right));
9587         
9588         aopOp(result,ic,FALSE);
9589         
9590         /* if the value is already in a pointer register
9591         then don't need anything more */
9592         if (!AOP_INPREG(AOP(result))) {
9593                 /* otherwise get a free pointer register */
9594                 aop = newAsmop(0);
9595                 preg = getFreePtr(ic,&aop,FALSE);
9596                 pic14_emitcode("mov","%s,%s",
9597                         preg->name,
9598                         aopGet(AOP(result),0,FALSE,TRUE));
9599                 rname = preg->name ;
9600         } else
9601                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9602         
9603         freeAsmop(result,NULL,ic,TRUE);
9604         aopOp (right,ic,FALSE);
9605         
9606         /* if bitfield then unpack the bits */
9607         if (IS_BITFIELD(retype)) 
9608                 genPackBits (retype,result,right,rname,PPOINTER);
9609         else {
9610                 /* we have can just get the values */
9611                 int size = AOP_SIZE(right);
9612                 int offset = 0 ;  
9613                 
9614                 while (size--) {
9615                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9616                         
9617                         MOVA(l);
9618                         pic14_emitcode("movx","@%s,a",rname);
9619                         
9620                         if (size)
9621                                 pic14_emitcode("inc","%s",rname);
9622                         
9623                         offset++;
9624                 }
9625         }
9626         
9627         /* now some housekeeping stuff */
9628         if (aop) {
9629                 /* we had to allocate for this iCode */
9630                 freeAsmop(NULL,aop,ic,TRUE);
9631         } else { 
9632         /* we did not allocate which means left
9633         already in a pointer register, then
9634         if size > 0 && this could be used again
9635         we have to point it back to where it 
9636                 belongs */
9637                 if (AOP_SIZE(right) > 1 &&
9638                         !OP_SYMBOL(result)->remat &&
9639                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9640                         ic->depth )) {
9641                         int size = AOP_SIZE(right) - 1;
9642                         while (size--)
9643                                 pic14_emitcode("dec","%s",rname);
9644                 }
9645         }
9646         
9647         /* done */
9648         freeAsmop(right,NULL,ic,TRUE);
9649         
9650         
9651 }
9652
9653 /*-----------------------------------------------------------------*/
9654 /* genFarPointerSet - set value from far space                     */
9655 /*-----------------------------------------------------------------*/
9656 static void genFarPointerSet (operand *right,
9657                                                           operand *result, iCode *ic)
9658 {
9659         int size, offset ;
9660         sym_link *retype = getSpec(operandType(right));
9661         
9662         FENTRY;
9663         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9664         aopOp(result,ic,FALSE);
9665         
9666         /* if the operand is already in dptr 
9667         then we do nothing else we move the value to dptr */
9668         if (AOP_TYPE(result) != AOP_STR) {
9669                 /* if this is remateriazable */
9670                 if (AOP_TYPE(result) == AOP_IMMD)
9671                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9672                 else { /* we need to get it byte by byte */
9673                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9674                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9675                         if (options.model == MODEL_FLAT24)
9676                         {
9677                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9678                         }
9679                 }
9680         }
9681         /* so dptr know contains the address */
9682         freeAsmop(result,NULL,ic,TRUE);
9683         aopOp(right,ic,FALSE);
9684         
9685         /* if bit then unpack */
9686         if (IS_BITFIELD(retype)) 
9687                 genPackBits(retype,result,right,"dptr",FPOINTER);
9688         else {
9689                 size = AOP_SIZE(right);
9690                 offset = 0 ;
9691                 
9692                 while (size--) {
9693                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9694                         MOVA(l);
9695                         pic14_emitcode("movx","@dptr,a");
9696                         if (size)
9697                                 pic14_emitcode("inc","dptr");
9698                 }
9699         }
9700         
9701         freeAsmop(right,NULL,ic,TRUE);
9702 }
9703
9704 /*-----------------------------------------------------------------*/
9705 /* genGenPointerSet - set value from generic pointer space         */
9706 /*-----------------------------------------------------------------*/
9707 static void genGenPointerSet (operand *right,
9708                                                           operand *result, iCode *ic)
9709 {
9710         sym_link *ptype = operandType(result);
9711         sym_link *retype = getSpec(operandType(right));
9712         sym_link *letype = getSpec (ptype);
9713         
9714         FENTRY;
9715         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9716         
9717         aopOp(result,ic,FALSE);
9718         aopOp(right,ic,FALSE);
9719         
9720         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9721         
9722         /* if the operand is already in dptr 
9723         then we do nothing else we move the value to dptr */
9724         if (AOP_TYPE(result) != AOP_STR) {
9725                 /* if this is remateriazable */
9726                 if (AOP_TYPE(result) == AOP_IMMD) {
9727                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9728                         pic14_emitcode("mov","b,%s + 1",aopGet(AOP(result),0,TRUE,FALSE));
9729                 }
9730                 else {
9731                         emitpcode(POC_MOVFW,popGet(AOP(result),0));
9732                         emitpcode(POC_MOVWF,popCopyReg(&pc_fsr));
9733
9734                         /* Must set/reset IRP bit for use with FSR. */
9735                         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9736                         SetIrp(result);
9737                 }
9738         }
9739
9740         /* if bitfield then unpack the bits */
9741         if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
9742                 genPackBits ((IS_BITFIELD (retype) ? retype : letype),result, right, "indf", POINTER);
9743         } else {
9744                 /* we have can just get the values */
9745                 int size = AOP_SIZE(right);
9746                 int offset = 0 ;    
9747                 
9748                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9749                 while (size--) {
9750                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9751                         if (*l == '@' ) {
9752                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9753                         } else {
9754                                 if (AOP_TYPE(right) == AOP_LIT) {
9755                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9756                                 } else {
9757                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9758                                 }
9759                                 emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9760                         }
9761                         if (size)
9762                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9763                         offset++;
9764                 }
9765         }
9766         
9767         freeAsmop(right,NULL,ic,TRUE);
9768         freeAsmop(result,NULL,ic,TRUE);
9769 }
9770
9771 /*-----------------------------------------------------------------*/
9772 /* genPointerSet - stores the value into a pointer location        */
9773 /*-----------------------------------------------------------------*/
9774 static void genPointerSet (iCode *ic)
9775 {    
9776         operand *right, *result ;
9777         sym_link *type, *etype;
9778         int p_type;
9779         
9780         FENTRY;
9781         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9782         
9783         right = IC_RIGHT(ic);
9784         result = IC_RESULT(ic) ;
9785         
9786         /* depending on the type of pointer we need to
9787         move it to the correct pointer register */
9788         type = operandType(result);
9789         etype = getSpec(type);
9790         /* if left is of type of pointer then it is simple */
9791         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9792                 p_type = DCL_TYPE(type);
9793         }
9794         else {
9795                 /* we have to go by the storage class */
9796                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9797                 
9798                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9799                 /*      p_type = CPOINTER ;  */
9800                 /*  } */
9801                 /*  else */
9802                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9803                 /*    p_type = FPOINTER ; */
9804                 /*      else */
9805                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9806                 /*        p_type = PPOINTER ; */
9807                 /*    else */
9808                 /*        if (SPEC_OCLS(etype) == idata ) */
9809                 /*      p_type = IPOINTER ; */
9810                 /*        else */
9811                 /*      p_type = POINTER ; */
9812         }
9813         
9814         /* now that we have the pointer type we assign
9815         the pointer values */
9816         switch (p_type) {
9817                 
9818         case POINTER:
9819         case IPOINTER:
9820                 genNearPointerSet (right,result,ic);
9821                 break;
9822                 
9823         case PPOINTER:
9824                 genPagedPointerSet (right,result,ic);
9825                 break;
9826                 
9827         case FPOINTER:
9828                 genFarPointerSet (right,result,ic);
9829                 break;
9830                 
9831         case GPOINTER:
9832                 genGenPointerSet (right,result,ic);
9833                 break;
9834                 
9835         default:
9836                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9837                         "genPointerSet: illegal pointer type");
9838         }
9839 }
9840
9841 /*-----------------------------------------------------------------*/
9842 /* genIfx - generate code for Ifx statement                        */
9843 /*-----------------------------------------------------------------*/
9844 static void genIfx (iCode *ic, iCode *popIc)
9845 {
9846         operand *cond = IC_COND(ic);
9847         int isbit =0;
9848         
9849         FENTRY;
9850         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9851         
9852         aopOp(cond,ic,FALSE);
9853         
9854         /* get the value into acc */
9855         if (AOP_TYPE(cond) != AOP_CRY)
9856                 pic14_toBoolean(cond);
9857         else
9858                 isbit = 1;
9859         /* the result is now in the accumulator */
9860         freeAsmop(cond,NULL,ic,TRUE);
9861         
9862         /* if there was something to be popped then do it */
9863         if (popIc)
9864                 genIpop(popIc);
9865         
9866         /* if the condition is  a bit variable */
9867         if (isbit && IS_ITEMP(cond) && 
9868                 SPIL_LOC(cond)) {
9869                 genIfxJump(ic,SPIL_LOC(cond)->rname);
9870                 DEBUGpic14_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9871         }
9872         else {
9873                 if (isbit && !IS_ITEMP(cond))
9874                         genIfxJump(ic,OP_SYMBOL(cond)->rname);
9875                 else
9876                         genIfxJump(ic,"a");
9877         }
9878         ic->generated = 1;
9879         
9880 }
9881
9882 /*-----------------------------------------------------------------*/
9883 /* genAddrOf - generates code for address of                       */
9884 /*-----------------------------------------------------------------*/
9885 static void genAddrOf (iCode *ic)
9886 {
9887         operand *right, *result, *left;
9888         int size, offset ;
9889         
9890         FENTRY;
9891         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9892         
9893         
9894         //aopOp(IC_RESULT(ic),ic,FALSE);
9895         
9896         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9897         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9898         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9899         
9900         DEBUGpic14_AopType(__LINE__,left,right,result);
9901         assert (IS_SYMOP (left));
9902         
9903         /* sanity check: generic pointers to code space are not yet supported,
9904          * pionters to codespace must not be assigned addresses of __data values. */
9905  #if 0
9906         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9907         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)));
9908         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)));
9909         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)));
9910         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)));
9911 #endif
9912
9913         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9914           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9915                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9916                 OP_SYMBOL(left)->name);
9917         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9918           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9919                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9920                 OP_SYMBOL(left)->name);
9921         }
9922         
9923         size = AOP_SIZE(IC_RESULT(ic));
9924         offset = 0;
9925         
9926         while (size--) {
9927                 /* fixing bug #863624, reported from (errolv) */
9928                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9929                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9930                 
9931 #if 0
9932                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9933                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9934 #endif
9935                 offset++;
9936         }
9937         
9938         freeAsmop(left,NULL,ic,FALSE);
9939         freeAsmop(result,NULL,ic,TRUE);
9940         
9941 }
9942
9943 #if 0
9944 /*-----------------------------------------------------------------*/
9945 /* genFarFarAssign - assignment when both are in far space         */
9946 /*-----------------------------------------------------------------*/
9947 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9948 {
9949         int size = AOP_SIZE(right);
9950         int offset = 0;
9951         char *l ;
9952         /* first push the right side on to the stack */
9953         while (size--) {
9954                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9955                 MOVA(l);
9956                 pic14_emitcode ("push","acc");
9957         }
9958         
9959         freeAsmop(right,NULL,ic,FALSE);
9960         /* now assign DPTR to result */
9961         aopOp(result,ic,FALSE);
9962         size = AOP_SIZE(result);
9963         while (size--) {
9964                 pic14_emitcode ("pop","acc");
9965                 aopPut(AOP(result),"a",--offset);
9966         }
9967         freeAsmop(result,NULL,ic,FALSE);
9968         
9969 }
9970 #endif
9971
9972 /*-----------------------------------------------------------------*/
9973 /* genAssign - generate code for assignment                        */
9974 /*-----------------------------------------------------------------*/
9975 static void genAssign (iCode *ic)
9976 {
9977         operand *result, *right;
9978         int size, offset,know_W;
9979         unsigned long lit = 0L;
9980         
9981         result = IC_RESULT(ic);
9982         right  = IC_RIGHT(ic) ;
9983         
9984         FENTRY;
9985         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9986         
9987         /* if they are the same */
9988         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9989                 return ;
9990         
9991         aopOp(right,ic,FALSE);
9992         aopOp(result,ic,TRUE);
9993         
9994         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9995         
9996         /* if they are the same registers */
9997         if (pic14_sameRegs(AOP(right),AOP(result)))
9998                 goto release;
9999
10000         /* special case: assign from __code */
10001         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10002                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10003                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10004                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10005                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10006         {
10007           emitpComment ("genAssign from CODESPACE");
10008           genConstPointerGet (right, result, ic);
10009           goto release;
10010         }
10011         
10012         /* just for symmetry reasons... */
10013         if (!IS_ITEMP(result)
10014                 && IS_SYMOP (result)
10015                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10016         {
10017           assert ( !"cannot write to CODESPACE" );
10018         }
10019
10020         /* if the result is a bit */
10021         if (AOP_TYPE(result) == AOP_CRY) {
10022                 
10023         /* if the right size is a literal then
10024                 we know what the value is */
10025                 if (AOP_TYPE(right) == AOP_LIT) {
10026                         
10027                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10028                                 popGet(AOP(result),0));
10029                         
10030                         if (((int) operandLitValue(right))) 
10031                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10032                                 AOP(result)->aopu.aop_dir,
10033                                 AOP(result)->aopu.aop_dir);
10034                         else
10035                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10036                                 AOP(result)->aopu.aop_dir,
10037                                 AOP(result)->aopu.aop_dir);
10038                         goto release;
10039                 }
10040                 
10041                 /* the right is also a bit variable */
10042                 if (AOP_TYPE(right) == AOP_CRY) {
10043                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10044                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10045                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10046                         
10047                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10048                                 AOP(result)->aopu.aop_dir,
10049                                 AOP(result)->aopu.aop_dir);
10050                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10051                                 AOP(right)->aopu.aop_dir,
10052                                 AOP(right)->aopu.aop_dir);
10053                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10054                                 AOP(result)->aopu.aop_dir,
10055                                 AOP(result)->aopu.aop_dir);
10056                         goto release ;
10057                 }
10058                 
10059                 /* we need to or */
10060                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10061                 pic14_toBoolean(right);
10062                 emitSKPZ;
10063                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10064                 //aopPut(AOP(result),"a",0);
10065                 goto release ;
10066         }
10067         
10068         /* bit variables done */
10069         /* general case */
10070         size = AOP_SIZE(result);
10071         offset = 0 ;
10072         if(AOP_TYPE(right) == AOP_LIT)
10073                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10074         
10075         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10076                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10077                 if(aopIdx(AOP(result),0) == 4) {
10078                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10079                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10080                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10081                         goto release;
10082                 } else
10083                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10084         }
10085         
10086         know_W=-1;
10087         while (size--) {
10088                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10089                 if(AOP_TYPE(right) == AOP_LIT) {
10090                         if(lit&0xff) {
10091                                 if(know_W != (int)(lit&0xff))
10092                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10093                                 know_W = lit&0xff;
10094                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10095                         } else
10096                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10097                         
10098                         lit >>= 8;
10099                         
10100                 } else if (AOP_TYPE(right) == AOP_CRY) {
10101                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10102                         if(offset == 0) {
10103                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10104                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10105                         }
10106                 } else {
10107                         mov2w (AOP(right), offset);
10108                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10109                 }
10110                 
10111                 offset++;
10112         }
10113         
10114         
10115 release:
10116         freeAsmop (right,NULL,ic,FALSE);
10117         freeAsmop (result,NULL,ic,TRUE);
10118 }   
10119
10120 /*-----------------------------------------------------------------*/
10121 /* genJumpTab - genrates code for jump table                       */
10122 /*-----------------------------------------------------------------*/
10123 static void genJumpTab (iCode *ic)
10124 {
10125         symbol *jtab;
10126         char *l;
10127         
10128         FENTRY;
10129         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10130         
10131         aopOp(IC_JTCOND(ic),ic,FALSE);
10132         /* get the condition into accumulator */
10133         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10134         MOVA(l);
10135         /* multiply by three */
10136         pic14_emitcode("add","a,acc");
10137         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10138         
10139         jtab = newiTempLabel(NULL);
10140         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10141         pic14_emitcode("jmp","@a+dptr");
10142         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10143         
10144         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10145         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10146         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10147         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10148         emitSKPNC;
10149         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10150         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10151         emitpLabel(jtab->key);
10152         
10153         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10154         
10155         /* now generate the jump labels */
10156         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10157         jtab = setNextItem(IC_JTLABELS(ic))) {
10158                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10159                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10160                 
10161         }
10162         
10163 }
10164
10165 /*-----------------------------------------------------------------*/
10166 /* genMixedOperation - gen code for operators between mixed types  */
10167 /*-----------------------------------------------------------------*/
10168 /*
10169 TSD - Written for the PIC port - but this unfortunately is buggy.
10170 This routine is good in that it is able to efficiently promote 
10171 types to different (larger) sizes. Unfortunately, the temporary
10172 variables that are optimized out by this routine are sometimes
10173 used in other places. So until I know how to really parse the 
10174 iCode tree, I'm going to not be using this routine :(.
10175 */
10176 static int genMixedOperation (iCode *ic)
10177 {
10178         FENTRY;
10179 #if 0
10180         operand *result = IC_RESULT(ic);
10181         sym_link *ctype = operandType(IC_LEFT(ic));
10182         operand *right = IC_RIGHT(ic);
10183         int ret = 0;
10184         int big,small;
10185         int offset;
10186         
10187         iCode *nextic;
10188         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10189         
10190         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10191         
10192         nextic = ic->next;
10193         if(!nextic)
10194                 return 0;
10195         
10196         nextright = IC_RIGHT(nextic);
10197         nextleft  = IC_LEFT(nextic);
10198         nextresult = IC_RESULT(nextic);
10199         
10200         aopOp(right,ic,FALSE);
10201         aopOp(result,ic,FALSE);
10202         aopOp(nextright,  nextic, FALSE);
10203         aopOp(nextleft,   nextic, FALSE);
10204         aopOp(nextresult, nextic, FALSE);
10205         
10206         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10207                 
10208                 operand *t = right;
10209                 right = nextright;
10210                 nextright = t; 
10211                 
10212                 pic14_emitcode(";remove right +","");
10213                 
10214         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10215         /*
10216         operand *t = right;
10217         right = nextleft;
10218         nextleft = t; 
10219                 */
10220                 pic14_emitcode(";remove left +","");
10221         } else
10222                 return 0;
10223         
10224         big = AOP_SIZE(nextleft);
10225         small = AOP_SIZE(nextright);
10226         
10227         switch(nextic->op) {
10228                 
10229         case '+':
10230                 pic14_emitcode(";optimize a +","");
10231                 /* if unsigned or not an integral type */
10232                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10233                         pic14_emitcode(";add a bit to something","");
10234                 } else {
10235                         
10236                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10237                         
10238                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10239                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10240                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10241                         } else
10242                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10243                         
10244                         offset = 0;
10245                         while(--big) {
10246                                 
10247                                 offset++;
10248                                 
10249                                 if(--small) {
10250                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10251                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10252                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10253                                         }
10254                                         
10255                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10256                                         emitSKPNC;
10257                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10258                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10259                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10260                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10261                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10262                                         
10263                                 } else {
10264                                         pic14_emitcode("rlf","known_zero,w");
10265                                         
10266                                         /*
10267                                         if right is signed
10268                                         btfsc  right,7
10269                                         addlw ff
10270                                         */
10271                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10272                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10273                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10274                                         } else {
10275                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10276                                         }
10277                                 }
10278                         }
10279                         ret = 1;
10280                 }
10281         }
10282         ret = 1;
10283         
10284 release:
10285         freeAsmop(right,NULL,ic,TRUE);
10286         freeAsmop(result,NULL,ic,TRUE);
10287         freeAsmop(nextright,NULL,ic,TRUE);
10288         freeAsmop(nextleft,NULL,ic,TRUE);
10289         if(ret)
10290                 nextic->generated = 1;
10291         
10292         return ret;
10293 #else
10294         return 0;
10295 #endif
10296 }
10297 /*-----------------------------------------------------------------*/
10298 /* genCast - gen code for casting                                  */
10299 /*-----------------------------------------------------------------*/
10300 static void genCast (iCode *ic)
10301 {
10302         operand *result = IC_RESULT(ic);
10303         sym_link *ctype = operandType(IC_LEFT(ic));
10304         sym_link *rtype = operandType(IC_RIGHT(ic));
10305         operand *right = IC_RIGHT(ic);
10306         int size, offset ;
10307         
10308         FENTRY;
10309         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10310         /* if they are equivalent then do nothing */
10311         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10312                 return ;
10313         
10314         aopOp(right,ic,FALSE) ;
10315         aopOp(result,ic,FALSE);
10316         
10317         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10318         
10319         /* if the result is a bit */
10320         if (AOP_TYPE(result) == AOP_CRY) {
10321         /* if the right size is a literal then
10322                 we know what the value is */
10323                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10324                 if (AOP_TYPE(right) == AOP_LIT) {
10325                         
10326                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10327                                 popGet(AOP(result),0));
10328                         
10329                         if (((int) operandLitValue(right))) 
10330                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
10331                                 AOP(result)->aopu.aop_dir,
10332                                 AOP(result)->aopu.aop_dir);
10333                         else
10334                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
10335                                 AOP(result)->aopu.aop_dir,
10336                                 AOP(result)->aopu.aop_dir);
10337                         
10338                         goto release;
10339                 }
10340                 
10341                 /* the right is also a bit variable */
10342                 if (AOP_TYPE(right) == AOP_CRY) {
10343                         
10344                         emitCLRC;
10345                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10346                         
10347                         pic14_emitcode("clrc","");
10348                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10349                                 AOP(right)->aopu.aop_dir,
10350                                 AOP(right)->aopu.aop_dir);
10351                         aopPut(AOP(result),"c",0);
10352                         goto release ;
10353                 }
10354                 
10355                 /* we need to or */
10356                 if (AOP_TYPE(right) == AOP_REG) {
10357                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10358                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
10359                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10360                 }
10361                 pic14_toBoolean(right);
10362                 aopPut(AOP(result),"a",0);
10363                 goto release ;
10364         }
10365         
10366         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10367                 int offset = 1;
10368                 size = AOP_SIZE(result);
10369                 
10370                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10371                 
10372                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10373                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10374                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10375                 
10376                 while (size--)
10377                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10378                 
10379                 goto release;
10380         }
10381         
10382         /* if they are the same size : or less */
10383         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10384                 
10385                 /* if they are in the same place */
10386                 if (pic14_sameRegs(AOP(right),AOP(result)))
10387                         goto release;
10388                 
10389                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10390                 if (IS_PTR_CONST(rtype))
10391                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10392                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10393                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10394                 
10395                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10396                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10397                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10398                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10399                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10400                         if(AOP_SIZE(result) <2)
10401                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10402                         
10403                 } else {
10404                         
10405                         /* if they in different places then copy */
10406                         size = AOP_SIZE(result);
10407                         offset = 0 ;
10408                         while (size--) {
10409                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10410                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10411                                 
10412                                 //aopPut(AOP(result),
10413                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10414                                 // offset);
10415                                 
10416                                 offset++;
10417                         }
10418                 }
10419                 goto release;
10420         }
10421         
10422         
10423         /* if the result is of type pointer */
10424         if (IS_PTR(ctype)) {
10425                 
10426                 int p_type;
10427                 sym_link *type = operandType(right);
10428                 sym_link *etype = getSpec(type);
10429                 DEBUGpic14_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10430                 
10431                 /* pointer to generic pointer */
10432                 if (IS_GENPTR(ctype)) {
10433                         char *l = zero;
10434                         
10435                         if (IS_PTR(type)) 
10436                                 p_type = DCL_TYPE(type);
10437                         else {
10438                                 /* we have to go by the storage class */
10439                                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10440                                 
10441                                 /*    if (SPEC_OCLS(etype)->codesp )  */
10442                                 /*        p_type = CPOINTER ;  */
10443                                 /*    else */
10444                                 /*        if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10445                                 /*      p_type = FPOINTER ; */
10446                                 /*        else */
10447                                 /*      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10448                                 /*          p_type = PPOINTER; */
10449                                 /*      else */
10450                                 /*          if (SPEC_OCLS(etype) == idata ) */
10451                                 /*        p_type = IPOINTER ; */
10452                                 /*          else */
10453                                 /*        p_type = POINTER ; */
10454                         }
10455                         
10456                         /* the first two bytes are known */
10457                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10458                         size = GPTRSIZE - 1; 
10459                         offset = 0 ;
10460                         while (size--) {
10461                                 if(offset < AOP_SIZE(right)) {
10462                                         DEBUGpic14_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10463                                         if ((AOP_TYPE(right) == AOP_PCODE) && 
10464                                                 AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10465                                                 emitpcode(POC_MOVLW, popGetAddr(AOP(right),offset,0));
10466                                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10467                                         } else { 
10468                                                 aopPut(AOP(result),
10469                                                         aopGet(AOP(right),offset,FALSE,FALSE),
10470                                                         offset);
10471                                         }
10472                                 } else 
10473                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
10474                                 offset++;
10475                         }
10476                         /* the last byte depending on type */
10477                         switch (p_type) {
10478                         case IPOINTER:
10479                         case POINTER:
10480                                 emitpcode(POC_CLRF,popGet(AOP(result),GPTRSIZE - 1));
10481                                 break;
10482                         case FPOINTER:
10483                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10484                                 l = one;
10485                                 break;
10486                         case CPOINTER:
10487                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10488                                 l = "#0x02";
10489                                 break;        
10490                         case PPOINTER:
10491                                 pic14_emitcode(";BUG!? ","%d",__LINE__);
10492                                 l = "#0x03";
10493                                 break;
10494                                 
10495                         default:
10496                                 /* this should never happen */
10497                                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10498                                         "got unknown pointer type");
10499                                 exit(1);
10500                         }
10501                         //aopPut(AOP(result),l, GPTRSIZE - 1);      
10502                         goto release ;
10503                 }
10504                 
10505                 /* just copy the pointers */
10506                 size = AOP_SIZE(result);
10507                 offset = 0 ;
10508                 while (size--) {
10509                         aopPut(AOP(result),
10510                                 aopGet(AOP(right),offset,FALSE,FALSE),
10511                                 offset);
10512                         offset++;
10513                 }
10514                 goto release ;
10515         }
10516         
10517         
10518         
10519         /* so we now know that the size of destination is greater
10520         than the size of the source.
10521         Now, if the next iCode is an operator then we might be
10522         able to optimize the operation without performing a cast.
10523         */
10524         if(genMixedOperation(ic))
10525                 goto release;
10526         
10527         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10528         
10529         /* we move to result for the size of source */
10530         size = AOP_SIZE(right);
10531         offset = 0 ;
10532         while (size--) {
10533                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10534                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10535                 offset++;
10536         }
10537         
10538         /* now depending on the sign of the destination */
10539         size = AOP_SIZE(result) - AOP_SIZE(right);
10540         /* if unsigned or not an integral type */
10541         if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10542                 while (size--)
10543                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10544         } else {
10545                 /* we need to extend the sign :{ */
10546                 
10547                 if(size == 1) {
10548                         /* Save one instruction of casting char to int */
10549                         emitpcode(POC_CLRF,   popGet(AOP(result),offset));
10550                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10551                         emitpcode(POC_DECF,   popGet(AOP(result),offset));
10552                 } else {
10553                         emitpcodeNULLop(POC_CLRW);
10554                         
10555                         if(offset)
10556                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10557                         else
10558                                 emitpcode(POC_BTFSC,   newpCodeOpBit(aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10559                         
10560                         emitpcode(POC_MOVLW,   popGetLit(0xff));
10561                         
10562                         while (size--)
10563                                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset++));
10564                 }
10565         }
10566         
10567 release:
10568         freeAsmop(right,NULL,ic,TRUE);
10569         freeAsmop(result,NULL,ic,TRUE);
10570         
10571 }
10572
10573 /*-----------------------------------------------------------------*/
10574 /* genDjnz - generate decrement & jump if not zero instrucion      */
10575 /*-----------------------------------------------------------------*/
10576 static int genDjnz (iCode *ic, iCode *ifx)
10577 {
10578         symbol *lbl, *lbl1;
10579         FENTRY;
10580         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10581         
10582         if (!ifx)
10583                 return 0;
10584         
10585                 /* if the if condition has a false label
10586         then we cannot save */
10587         if (IC_FALSE(ifx))
10588                 return 0;
10589         
10590                 /* if the minus is not of the form 
10591         a = a - 1 */
10592         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10593                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10594                 return 0;
10595         
10596         if (operandLitValue(IC_RIGHT(ic)) != 1)
10597                 return 0;
10598         
10599                 /* if the size of this greater than one then no
10600         saving */
10601         if (getSize(operandType(IC_RESULT(ic))) > 1)
10602                 return 0;
10603         
10604         /* otherwise we can save BIG */
10605         lbl = newiTempLabel(NULL);
10606         lbl1= newiTempLabel(NULL);
10607         
10608         aopOp(IC_RESULT(ic),ic,FALSE);
10609         
10610         if (IS_AOP_PREG(IC_RESULT(ic))) {
10611                 pic14_emitcode("dec","%s",
10612                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10613                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10614                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10615         } else {  
10616                 
10617                 
10618                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10619                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10620                 
10621                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10622                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10623                 
10624         }
10625         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10626         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10627         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10628         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10629         
10630         
10631         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10632         ifx->generated = 1;
10633         return 1;
10634 }
10635
10636 /*-----------------------------------------------------------------*/
10637 /* genReceive - generate code for a receive iCode                  */
10638 /*-----------------------------------------------------------------*/
10639 static void genReceive (iCode *ic)
10640 {
10641         FENTRY;
10642         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10643         
10644         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10645                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10646                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10647                 
10648                 int size = getSize(operandType(IC_RESULT(ic)));
10649                 int offset =  fReturnSizePic - size;
10650                 while (size--) {
10651                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10652                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10653                         offset++;
10654                 }
10655                 aopOp(IC_RESULT(ic),ic,FALSE);
10656                 size = AOP_SIZE(IC_RESULT(ic));
10657                 offset = 0;
10658                 while (size--) {
10659                         pic14_emitcode ("pop","acc");
10660                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10661                 }
10662                 
10663         } else {
10664                 _G.accInUse++;
10665                 aopOp(IC_RESULT(ic),ic,FALSE);
10666                 _G.accInUse--;
10667                 assignResultValue(IC_RESULT(ic));
10668         }
10669         
10670         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10671 }
10672
10673 /*-----------------------------------------------------------------*/
10674 /* genDummyRead - generate code for dummy read of volatiles        */
10675 /*-----------------------------------------------------------------*/
10676 static void
10677 genDummyRead (iCode * ic)
10678 {
10679         FENTRY;
10680         pic14_emitcode ("; genDummyRead","");
10681         pic14_emitcode ("; not implemented","");
10682         
10683         ic = ic;
10684 }
10685
10686 /*-----------------------------------------------------------------*/
10687 /* genpic14Code - generate code for pic14 based controllers        */
10688 /*-----------------------------------------------------------------*/
10689 /*
10690 * At this point, ralloc.c has gone through the iCode and attempted
10691 * to optimize in a way suitable for a PIC. Now we've got to generate
10692 * PIC instructions that correspond to the iCode.
10693 *
10694 * Once the instructions are generated, we'll pass through both the
10695 * peep hole optimizer and the pCode optimizer.
10696 *-----------------------------------------------------------------*/
10697
10698 void genpic14Code (iCode *lic)
10699 {
10700         iCode *ic;
10701         int cln = 0;
10702         const char *cline;
10703         
10704         FENTRY;
10705         lineHead = lineCurr = NULL;
10706         
10707         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10708         addpBlock(pb);
10709         
10710         /* if debug information required */
10711         if (options.debug && currFunc) { 
10712                 if (currFunc) {
10713                         debugFile->writeFunction (currFunc, lic);
10714                 }
10715         }
10716         
10717         
10718         for (ic = lic ; ic ; ic = ic->next ) {
10719                 
10720                 //DEBUGpic14_emitcode(";ic","");
10721                 //fprintf (stderr, "in ic loop\n");
10722                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10723                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10724                 
10725                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10726                   cln = ic->lineno;
10727                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10728                   cline = printCLine (ic->filename, ic->lineno);
10729                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10730                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10731                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10732                 }
10733                 
10734                 if (options.iCodeInAsm) {
10735                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10736                 }
10737                 /* if the result is marked as
10738                 spilt and rematerializable or code for
10739                 this has already been generated then
10740                 do nothing */
10741                 if (resultRemat(ic) || ic->generated ) 
10742                         continue ;
10743                 
10744                 /* depending on the operation */
10745                 switch (ic->op) {
10746                 case '!' :
10747                         genNot(ic);
10748                         break;
10749                         
10750                 case '~' :
10751                         genCpl(ic);
10752                         break;
10753                         
10754                 case UNARYMINUS:
10755                         genUminus (ic);
10756                         break;
10757                         
10758                 case IPUSH:
10759                         genIpush (ic);
10760                         break;
10761                         
10762                 case IPOP:
10763                         /* IPOP happens only when trying to restore a 
10764                         spilt live range, if there is an ifx statement
10765                         following this pop then the if statement might
10766                         be using some of the registers being popped which
10767                         would destory the contents of the register so
10768                         we need to check for this condition and handle it */
10769                         if (ic->next            && 
10770                                 ic->next->op == IFX &&
10771                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10772                                 genIfx (ic->next,ic);
10773                         else
10774                                 genIpop (ic);
10775                         break; 
10776                         
10777                 case CALL:
10778                         genCall (ic);
10779                         break;
10780                         
10781                 case PCALL:
10782                         genPcall (ic);
10783                         break;
10784                         
10785                 case FUNCTION:
10786                         genFunction (ic);
10787                         break;
10788                         
10789                 case ENDFUNCTION:
10790                         genEndFunction (ic);
10791                         break;
10792                         
10793                 case RETURN:
10794                         genRet (ic);
10795                         break;
10796                         
10797                 case LABEL:
10798                         genLabel (ic);
10799                         break;
10800                         
10801                 case GOTO:
10802                         genGoto (ic);
10803                         break;
10804                         
10805                 case '+' :
10806                         genPlus (ic) ;
10807                         break;
10808                         
10809                 case '-' :
10810                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10811                                 genMinus (ic);
10812                         break;
10813                         
10814                 case '*' :
10815                         genMult (ic);
10816                         break;
10817                         
10818                 case '/' :
10819                         genDiv (ic) ;
10820                         break;
10821                         
10822                 case '%' :
10823                         genMod (ic);
10824                         break;
10825                         
10826                 case '>' :
10827                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10828                         break;
10829                         
10830                 case '<' :
10831                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10832                         break;
10833                         
10834                 case LE_OP:
10835                 case GE_OP:
10836                 case NE_OP:
10837                         
10838                         /* note these two are xlated by algebraic equivalence
10839                         during parsing SDCC.y */
10840                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10841                                 "got '>=' or '<=' shouldn't have come here");
10842                         break;  
10843                         
10844                 case EQ_OP:
10845                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10846                         break;      
10847                         
10848                 case AND_OP:
10849                         genAndOp (ic);
10850                         break;
10851                         
10852                 case OR_OP:
10853                         genOrOp (ic);
10854                         break;
10855                         
10856                 case '^' :
10857                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10858                         break;
10859                         
10860                 case '|' :
10861                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10862                         break;
10863                         
10864                 case BITWISEAND:
10865                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10866                         break;
10867                         
10868                 case INLINEASM:
10869                         genInline (ic);
10870                         break;
10871                         
10872                 case RRC:
10873                         genRRC (ic);
10874                         break;
10875                         
10876                 case RLC:
10877                         genRLC (ic);
10878                         break;
10879                         
10880                 case GETHBIT:
10881                         genGetHbit (ic);
10882                         break;
10883                         
10884                 case LEFT_OP:
10885                         genLeftShift (ic);
10886                         break;
10887                         
10888                 case RIGHT_OP:
10889                         genRightShift (ic);
10890                         break;
10891                         
10892                 case GET_VALUE_AT_ADDRESS:
10893                         genPointerGet(ic);
10894                         break;
10895                         
10896                 case '=' :
10897                         if (POINTER_SET(ic))
10898                                 genPointerSet(ic);
10899                         else
10900                                 genAssign(ic);
10901                         break;
10902                         
10903                 case IFX:
10904                         genIfx (ic,NULL);
10905                         break;
10906                         
10907                 case ADDRESS_OF:
10908                         genAddrOf (ic);
10909                         break;
10910                         
10911                 case JUMPTABLE:
10912                         genJumpTab (ic);
10913                         break;
10914                         
10915                 case CAST:
10916                         genCast (ic);
10917                         break;
10918                         
10919                 case RECEIVE:
10920                         genReceive(ic);
10921                         break;
10922                         
10923                 case SEND:
10924                         addSet(&_G.sendSet,ic);
10925                         break;
10926                         
10927                 case DUMMY_READ_VOLATILE:
10928                         genDummyRead (ic);
10929                         break;
10930                         
10931                 default :
10932                         ic = ic;
10933                 }
10934         }
10935
10936         
10937         /* now we are ready to call the
10938         peep hole optimizer */
10939         if (!options.nopeep) {
10940                 peepHole (&lineHead);
10941         }
10942         /* now do the actual printing */
10943         printLine (lineHead,codeOutFile);
10944         
10945 #ifdef PCODE_DEBUG
10946         DFPRINTF((stderr,"printing pBlock\n\n"));
10947         printpBlock(stdout,pb);
10948 #endif
10949         
10950         return;
10951 }
10952
10953 int
10954 aop_isLitLike (asmop *aop)
10955 {
10956   assert (aop);
10957   if (aop->type == AOP_LIT) return 1;
10958   if (aop->type == AOP_IMMD) return 1;
10959   if ((aop->type == AOP_PCODE) &&
10960                 ((aop->aopu.pcop->type == PO_LITERAL) || (aop->aopu.pcop->type == PO_IMMEDIATE)))
10961   {
10962     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10963      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10964     return 1;
10965   }
10966   return 0;
10967 }
10968
10969 int
10970 op_isLitLike (operand *op)
10971 {
10972   assert (op);
10973   if (aop_isLitLike (AOP(op))) return 1;
10974   return 0;
10975 }