* src/pic/gen.c (genFunction,genCall): drop "same code page"
[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     cont'd   -  Raphael Neider <rneider AT web.de> (2005)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
30       Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h" 
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "glue.h"
46
47 /* When changing these, you must also update the assembler template
48  * in device/lib/libsdcc/macros.inc */
49 #define GPTRTAG_DATA    0x00
50 #define GPTRTAG_CODE    0x80
51
52 /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
53 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
54 #define PIC_IS_FARPTR(x)        (PIC_IS_DATA_PTR(x))
55
56 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
57 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
58 void genMult8X8_8 (operand *, operand *,operand *);
59 extern void printpBlock(FILE *of, pBlock *pb);
60
61 static int labelOffset=0;
62 extern int debug_verbose;
63 extern int pic14_hasInterrupt;
64 //static int optimized_for_speed = 0;
65
66 /* max_key keeps track of the largest label number used in 
67 a function. This is then used to adjust the label offset
68 for the next function.
69 */
70 static int max_key=0;
71 static int GpsuedoStkPtr=0;
72 static int pic14_inISR = 0;
73
74 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
75 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
76 const char *AopType(short type);
77
78 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
79
80 /* this is the down and dirty file with all kinds of 
81 kludgy & hacky stuff. This is what it is all about
82 CODE GENERATION for a specific MCU . some of the
83 routines may be reusable, will have to see */
84
85 static char *zero = "#0x00";
86 static char *one  = "#0x01";
87 static char *spname = "sp";
88
89 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
90 unsigned fReturnSizePic = 4; /* shared with ralloc.c */
91 static char **fReturn = fReturnpic14;
92
93 //static char *accUse[] = {"a","b"};
94
95 //static short rbank = -1;
96
97 static struct {
98         short r0Pushed;
99         short r1Pushed;
100         short accInUse;
101         short inLine;
102         short debugLine;
103         short nRegsSaved;
104         set *sendSet;
105 } _G;
106
107 /* Resolved ifx structure. This structure stores information
108 about an iCode ifx that makes it easier to generate code.
109 */
110 typedef struct resolvedIfx {
111         symbol *lbl;     /* pointer to a label */
112         int condition;   /* true or false ifx */
113         int generated;   /* set true when the code associated with the ifx
114                           * is generated */
115 } resolvedIfx;
116
117 extern int pic14_ptrRegReq ;
118 extern int pic14_nRegs;
119 extern FILE *codeOutFile;
120 static void saverbank (int, iCode *,bool);
121
122 static lineNode *lineHead = NULL;
123 static lineNode *lineCurr = NULL;
124
125 #if 0
126 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
127 0xE0, 0xC0, 0x80, 0x00};
128 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
129 0x07, 0x03, 0x01, 0x00};
130 #endif
131
132 static  pBlock *pb;
133
134 /*-----------------------------------------------------------------*/
135 /*      my_powof2(n) - If `n' is an integaer power of 2, then the          */
136 /*                                 exponent of 2 is returned, otherwise -1 is      */
137 /*                                 returned.                                                                       */
138 /* note that this is similar to the function `powof2' in SDCCsymt  */
139 /* if(n == 2^y)                                                                                                    */
140 /*       return y;                                                                                                         */
141 /* return -1;                                                                                                      */
142 /*-----------------------------------------------------------------*/
143 static int my_powof2 (unsigned long num)
144 {
145         if(num) {
146                 if( (num & (num-1)) == 0) {
147                         int nshifts = -1;
148                         while(num) {
149                                 num>>=1;
150                                 nshifts++;
151                         }
152                         return nshifts;
153                 }
154         }
155         
156         return -1;
157 }
158
159 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result)
160 {
161         
162         DEBUGpic14_emitcode ("; ","line = %d result %s=%s, size=%d, left %s=%s, size=%d, right %s=%s, size=%d",
163                 line_no,
164                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
165                 ((result) ? aopGet(AOP(result),0,TRUE,FALSE) : "-"),
166                 ((result) ? AOP_SIZE(result) : 0),
167                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
168                 ((left)   ? aopGet(AOP(left),0,TRUE,FALSE) : "-"),
169                 ((left)   ? AOP_SIZE(left) : 0),
170                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
171                 ((right)  ? aopGet(AOP(right),0,FALSE,FALSE) : "-"),
172                 ((right)  ? AOP_SIZE(right) : 0));
173         
174 }
175
176 void DEBUGpic14_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
177 {
178         
179         DEBUGpic14_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
180                 line_no,
181                 ((result) ? AopType(AOP_TYPE(result)) : "-"),
182                 ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
183                 ((left)   ? AopType(AOP_TYPE(left)) : "-"),
184                 ((left)   ? (SPEC_USIGN(operandType(left))       ? 'u' : 's') : '-'),
185                 ((right)  ? AopType(AOP_TYPE(right)) : "-"),
186                 ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
187         
188 }
189
190 void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
191 {
192         va_list ap;
193         char lb[INITIAL_INLINEASM];  
194         unsigned char *lbp = (unsigned char *)lb;
195         
196         if(!debug_verbose && !options.debug)
197                 return;
198         
199         va_start(ap,fmt);   
200         
201         if (inst && *inst) {
202                 if (fmt && *fmt)
203                         sprintf(lb,"%s\t",inst);
204                 else
205                         sprintf(lb,"%s",inst);
206                 vsprintf(lb+(strlen(lb)),fmt,ap);
207         }  else
208                 vsprintf(lb,fmt,ap);
209         
210         while (isspace(*lbp)) lbp++;
211         
212         if (lbp && *lbp) 
213                 lineCurr = (lineCurr ?
214                 connectLine(lineCurr,newLineNode(lb)) :
215         (lineHead = newLineNode(lb)));
216         lineCurr->isInline = _G.inLine;
217         lineCurr->isDebug  = _G.debugLine;
218         
219         addpCode2pBlock(pb,newpCodeCharP(lb));
220         
221         va_end(ap);
222 }
223
224 static void Safe_vsnprintf (char *buf, size_t size, const char *fmt, va_list ap)
225 {
226 #if defined (HAVE_VSNPRINTF)
227   vsnprintf (buf, size, fmt, ap);
228 #elif defined (HAVE_VSPRINTF)
229   vsprintf (buf, size, fmt, ap);
230   if (strlen (buf) >= size)
231   {
232     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
233   }
234 #elif defined (HAVE_SNPRINTF)
235   snprintf (buf, size, "vs(n)printf required");
236 #elif defined (HAVE_SRINTF)
237   sprintf (buf, "vs(n)printf required");
238   if (strlen (buf) >= size)
239   {
240     fprintf (stderr, "Safe_vsnprintf: buffer (size %u) has overflown\n", size);
241   }
242 #else
243   assert ( !"neither vsnprintf nor vsprintf is present -- unable to proceed" );
244 #endif
245 }
246
247 void emitpComment (const char *fmt, ...)
248 {
249   va_list va;
250   char buffer[4096];
251   
252   va_start (va, fmt);
253   if (pb) {
254     Safe_vsnprintf (buffer, 4096, fmt, va);
255     //fprintf (stderr, "%s\n" ,buffer);
256     addpCode2pBlock (pb, newpCodeCharP (buffer));
257 #if 0
258   } else {
259     Safe_vsnprintf (buffer, 4096, fmt, va);
260     fprintf (stderr, "No current pBlock -- discarding comment [%s]\n", buffer);
261 #endif
262   }
263   va_end (va);
264 }
265
266 void emitpLabel(int key)
267 {
268         addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
269 }
270
271 /* gen.h defines a macro emitpcode that should be used to call emitpcode
272  * as this allows for easy debugging (ever asked the question: where was
273  * this instruction geenrated? Here is the answer... */
274 void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
275 {
276         if(pcop)
277                 addpCode2pBlock(pb,newpCode(poc,pcop));
278         else {
279                 static int has_warned = 0;
280                 
281                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
282                 if (!has_warned) {
283                         has_warned = 1;
284                         fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
285                 }
286         }
287 }
288
289 void emitpcodeNULLop(PIC_OPCODE poc)
290 {
291         
292         addpCode2pBlock(pb,newpCode(poc,NULL));
293         
294 }
295
296
297 /*-----------------------------------------------------------------*/
298 /* pic14_emitcode - writes the code into a file : for now it is simple    */
299 /*-----------------------------------------------------------------*/
300 void pic14_emitcode (char *inst,char *fmt, ...)
301 {
302         va_list ap;
303         char lb[INITIAL_INLINEASM];  
304         unsigned char *lbp = (unsigned char *)lb;
305         
306         va_start(ap,fmt);   
307         
308         if (inst && *inst) {
309                 if (fmt && *fmt)
310                         sprintf(lb,"%s\t",inst);
311                 else
312                         sprintf(lb,"%s",inst);
313                 vsprintf(lb+(strlen(lb)),fmt,ap);
314         }  else
315                 vsprintf(lb,fmt,ap);
316         
317         while (isspace(*lbp)) lbp++;
318         
319         if (lbp && *lbp) 
320                 lineCurr = (lineCurr ?
321                 connectLine(lineCurr,newLineNode(lb)) :
322         (lineHead = newLineNode(lb)));
323         lineCurr->isInline = _G.inLine;
324         lineCurr->isDebug  = _G.debugLine;
325         
326         if(debug_verbose)
327                 addpCode2pBlock(pb,newpCodeCharP(lb));
328         
329         va_end(ap);
330 }
331
332 /*-----------------------------------------------------------------*/
333 /* pic14_emitDebuggerSymbol - associate the current code location  */
334 /*       with a debugger symbol                                                                            */
335 /*-----------------------------------------------------------------*/
336 void
337 pic14_emitDebuggerSymbol (char * debugSym)
338 {
339         _G.debugLine = 1;
340         pic14_emitcode ("", ";%s ==.", debugSym);
341         _G.debugLine = 0;
342 }
343
344 #if 0
345 /*-----------------------------------------------------------------*/
346 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
347 /*-----------------------------------------------------------------*/
348 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
349 {
350         bool r0iu = FALSE , r1iu = FALSE;
351         bool r0ou = FALSE , r1ou = FALSE;
352         
353         /* the logic: if r0 & r1 used in the instruction
354         then we are in trouble otherwise */
355         
356         /* first check if r0 & r1 are used by this
357         instruction, in which case we are in trouble */
358         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
359                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
360         {
361                 goto endOfWorld;          
362         }
363         
364         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
365         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
366         
367         /* if no usage of r0 then return it */
368         if (!r0iu && !r0ou) {
369                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
370                 (*aopp)->type = AOP_R0;
371                 
372                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
373         }
374         
375         /* if no usage of r1 then return it */
376         if (!r1iu && !r1ou) {
377                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
378                 (*aopp)->type = AOP_R1;
379                 
380                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
381         }    
382         
383         /* now we know they both have usage */
384         /* if r0 not used in this instruction */
385         if (!r0iu) {
386                 /* push it if not already pushed */
387                 if (!_G.r0Pushed) {
388                         //pic14_emitcode ("push","%s",
389                         //                pic14_regWithIdx(R0_IDX)->dname);
390                         _G.r0Pushed++ ;
391                 }
392                 
393                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
394                 (*aopp)->type = AOP_R0;
395                 
396                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
397         }
398         
399         /* if r1 not used then */
400         
401         if (!r1iu) {
402                 /* push it if not already pushed */
403                 if (!_G.r1Pushed) {
404                         //pic14_emitcode ("push","%s",
405                         //                pic14_regWithIdx(R1_IDX)->dname);
406                         _G.r1Pushed++ ;
407                 }
408                 
409                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
410                 (*aopp)->type = AOP_R1;
411                 return pic14_regWithIdx(R1_IDX);
412         }
413         
414 endOfWorld :
415         /* I said end of world but not quite end of world yet */
416         /* if this is a result then we can push it on the stack*/
417         if (result) {
418                 (*aopp)->type = AOP_STK;        
419                 return NULL;
420         }
421         
422         /* other wise this is true end of the world */
423         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
424                 "getFreePtr should never reach here");
425         exit(0);
426 }
427 #endif
428
429 /*-----------------------------------------------------------------*/
430 /* newAsmop - creates a new asmOp                                                                  */
431 /*-----------------------------------------------------------------*/
432 asmop *newAsmop (short type)
433 {
434         asmop *aop;
435         
436         aop = Safe_calloc(1,sizeof(asmop));
437         aop->type = type;
438         return aop;
439 }
440
441 static void genSetDPTR(int n)
442 {
443         if (!n)
444         {
445                 pic14_emitcode(";", "Select standard DPTR");
446                 pic14_emitcode("mov", "dps, #0x00");
447         }
448         else
449         {
450                 pic14_emitcode(";", "Select alternate DPTR");
451                 pic14_emitcode("mov", "dps, #0x01");
452         }
453 }
454
455 /*-----------------------------------------------------------------*/
456 /* resolveIfx - converts an iCode ifx into a form more useful for  */
457 /*                              generating code                                                                    */
458 /*-----------------------------------------------------------------*/
459 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
460 {
461         if(!resIfx) 
462                 return;
463         
464         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
465         
466         resIfx->condition = 1;  /* assume that the ifx is true */
467         resIfx->generated = 0;  /* indicate that the ifx has not been used */
468         
469         if(!ifx) {
470                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
471                                                                                         /*
472                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
473                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
474                 */
475         } else {
476                 if(IC_TRUE(ifx)) {
477                         resIfx->lbl = IC_TRUE(ifx);
478                 } else {
479                         resIfx->lbl = IC_FALSE(ifx);
480                         resIfx->condition = 0;
481                 }
482                 /*
483                 if(IC_TRUE(ifx)) 
484                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
485                 if(IC_FALSE(ifx)) 
486                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
487                 */
488         }
489         
490         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
491         
492 }
493 /*-----------------------------------------------------------------*/
494 /* pointerCode - returns the code for a pointer type                       */
495 /*-----------------------------------------------------------------*/
496 #if 0
497 static int pointerCode (sym_link *etype)
498 {
499         
500         return PTR_TYPE(SPEC_OCLS(etype));
501         
502 }
503 #endif
504
505 /*-----------------------------------------------------------------*/
506 /* aopForSym - for a true symbol                                                                   */
507 /*-----------------------------------------------------------------*/
508 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
509 {
510         asmop *aop;
511         memmap *space= SPEC_OCLS(sym->etype);
512         
513         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
514         /* if already has one */
515         if (sym->aop)
516                 return sym->aop;
517         
518 #if 0
519         /* assign depending on the storage class */
520         /* if it is on the stack or indirectly addressable */
521         /* space we need to assign either r0 or r1 to it         */    
522         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
523                 sym->aop = aop = newAsmop(0);
524                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
525                 aop->size = getSize(sym->type);
526                 
527                 /* now assign the address of the variable to 
528                 the pointer register */
529                 if (aop->type != AOP_STK) {
530                         
531                         if (sym->onStack) {
532                                 if ( _G.accInUse )
533                                         pic14_emitcode("push","acc");
534                                 
535                                 pic14_emitcode("mov","a,_bp");
536                                 pic14_emitcode("add","a,#0x%02x",
537                                         ((sym->stack < 0) ?
538                                         ((char)(sym->stack - _G.nRegsSaved )) :
539                                 ((char)sym->stack)) & 0xff);
540                                 pic14_emitcode("mov","%s,a",
541                                         aop->aopu.aop_ptr->name);
542                                 
543                                 if ( _G.accInUse )
544                                         pic14_emitcode("pop","acc");
545                         } else
546                                 pic14_emitcode("mov","%s,#%s",
547                                 aop->aopu.aop_ptr->name,
548                                 sym->rname);
549                         aop->paged = space->paged;
550                 } else
551                         aop->aopu.aop_stk = sym->stack;
552                 return aop;
553         }
554         
555         if (sym->onStack && options.stack10bit)
556         {
557                 /* It's on the 10 bit stack, which is located in
558                 * far data space.
559                 */
560                 
561                 //DEBUGpic14_emitcode(";","%d",__LINE__);
562                 
563                 if ( _G.accInUse )
564                         pic14_emitcode("push","acc");
565                 
566                 pic14_emitcode("mov","a,_bp");
567                 pic14_emitcode("add","a,#0x%02x",
568                         ((sym->stack < 0) ?
569                         ((char)(sym->stack - _G.nRegsSaved )) :
570                 ((char)sym->stack)) & 0xff);
571                 
572                 genSetDPTR(1);
573                 pic14_emitcode ("mov","dpx1,#0x40");
574                 pic14_emitcode ("mov","dph1,#0x00");
575                 pic14_emitcode ("mov","dpl1, a");
576                 genSetDPTR(0);
577                 
578                 if ( _G.accInUse )
579                         pic14_emitcode("pop","acc");
580                 
581                 sym->aop = aop = newAsmop(AOP_DPTR2);
582                 aop->size = getSize(sym->type); 
583                 return aop;
584         }
585 #endif
586
587         //DEBUGpic14_emitcode(";","%d",__LINE__);
588         /* if in bit space */
589         if (IN_BITSPACE(space)) {
590                 sym->aop = aop = newAsmop (AOP_CRY);
591                 aop->aopu.aop_dir = sym->rname ;
592                 aop->size = getSize(sym->type);
593                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
594                 return aop;
595         }
596         /* if it is in direct space */
597         if (IN_DIRSPACE(space)) {
598                 sym->aop = aop = newAsmop (AOP_DIR);
599                 aop->aopu.aop_dir = sym->rname ;
600                 aop->size = getSize(sym->type);
601                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
602                 return aop;
603         }
604         
605         /* special case for a function */
606         if (IS_FUNC(sym->type)) {   
607                 
608                 sym->aop = aop = newAsmop(AOP_PCODE);
609                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
610                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
611                 PCOI(aop->aopu.pcop)->_function = 1;
612                 PCOI(aop->aopu.pcop)->index = 0;
613                 aop->size = FPTRSIZE; 
614                 /*
615                 sym->aop = aop = newAsmop(AOP_IMMD);    
616                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
617                 strcpy(aop->aopu.aop_immd,sym->rname);
618                 aop->size = FPTRSIZE; 
619                 */
620                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
621                 return aop;
622         }
623         
624         if (IS_ARRAY(sym->type)) {
625                 sym->aop = aop = newAsmop(AOP_PCODE);
626                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
627                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
628                 PCOI(aop->aopu.pcop)->_function = 0;
629                 PCOI(aop->aopu.pcop)->index = 0;
630                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
631                 
632                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
633                 return aop;
634         }
635         
636         /* only remaining is far space */
637         /* in which case DPTR gets the address */
638         sym->aop = aop = newAsmop(AOP_PCODE);
639         
640         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
641         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
642         PCOI(aop->aopu.pcop)->index = 0;
643         
644         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
645                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
646         
647         allocDirReg (IC_LEFT(ic));
648         
649         aop->size = FPTRSIZE;
650         /*
651         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
652         sym->aop = aop = newAsmop(AOP_DPTR);
653         pic14_emitcode ("mov","dptr,#%s", sym->rname);
654         aop->size = getSize(sym->type);
655         
656           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
657         */
658         
659         /* if it is in code space */
660         if (IN_CODESPACE(space))
661                 aop->code = 1;
662         
663         return aop;       
664 }
665
666 /*-----------------------------------------------------------------*/
667 /* aopForRemat - rematerialzes an object                                                   */
668 /*-----------------------------------------------------------------*/
669 static asmop *aopForRemat (operand *op) // x symbol *sym)
670 {
671         symbol *sym = OP_SYMBOL(op);
672         iCode *ic = NULL;
673         asmop *aop = newAsmop(AOP_PCODE);
674         int val = 0;
675         int offset = 0;
676         
677         ic = sym->rematiCode;
678
679         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
680         if(IS_OP_POINTER(op)) {
681                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
682         }
683         for (;;) {
684                 if (ic->op == '+') {
685                         val += (int) operandLitValue(IC_RIGHT(ic));
686                 } else if (ic->op == '-') {
687                         val -= (int) operandLitValue(IC_RIGHT(ic));
688                 } else
689                         break;
690                 
691                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
692         }
693         
694         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
695         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
696         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
697         PCOI(aop->aopu.pcop)->index = val;
698         
699         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
700                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
701                 val, IS_PTR_CONST(operandType(op)));
702         
703         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
704         
705         allocDirReg (IC_LEFT(ic));
706         
707         return aop;              
708 }
709
710 int aopIdx (asmop *aop, int offset)
711 {
712         if(!aop)
713                 return -1;
714         
715         if(aop->type !=  AOP_REG)
716                 return -2;
717         
718         return aop->aopu.aop_reg[offset]->rIdx;
719         
720 }
721 /*-----------------------------------------------------------------*/
722 /* regsInCommon - two operands have some registers in common       */
723 /*-----------------------------------------------------------------*/
724 static bool regsInCommon (operand *op1, operand *op2)
725 {
726         symbol *sym1, *sym2;
727         int i;
728         
729         /* if they have registers in common */
730         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
731                 return FALSE ;
732         
733         sym1 = OP_SYMBOL(op1);
734         sym2 = OP_SYMBOL(op2);
735         
736         if (sym1->nRegs == 0 || sym2->nRegs == 0)
737                 return FALSE ;
738         
739         for (i = 0 ; i < sym1->nRegs ; i++) {
740                 int j;
741                 if (!sym1->regs[i])
742                         continue ;
743                 
744                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
745                         if (!sym2->regs[j])
746                                 continue ;
747                         
748                         if (sym2->regs[j] == sym1->regs[i])
749                                 return TRUE ;
750                 }
751         }
752         
753         return FALSE ;
754 }
755
756 /*-----------------------------------------------------------------*/
757 /* operandsEqu - equivalent                                                                        */
758 /*-----------------------------------------------------------------*/
759 static bool operandsEqu ( operand *op1, operand *op2)
760 {
761         symbol *sym1, *sym2;
762         
763         /* if they not symbols */
764         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
765                 return FALSE;
766         
767         sym1 = OP_SYMBOL(op1);
768         sym2 = OP_SYMBOL(op2);
769         
770         /* if both are itemps & one is spilt
771         and the other is not then false */
772         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
773                 sym1->isspilt != sym2->isspilt )
774                 return FALSE ;
775         
776         /* if they are the same */
777         if (sym1 == sym2)
778                 return TRUE ;
779         
780         if (sym1->rname[0] && sym2->rname[0]
781                 && strcmp (sym1->rname, sym2->rname) == 0)
782                 return TRUE;
783         
784         
785         /* if left is a tmp & right is not */
786         if (IS_ITEMP(op1)  && 
787                 !IS_ITEMP(op2) &&
788                 sym1->isspilt  &&
789                 (sym1->usl.spillLoc == sym2))
790                 return TRUE;
791         
792         if (IS_ITEMP(op2)  && 
793                 !IS_ITEMP(op1) &&
794                 sym2->isspilt  &&
795                 sym1->level > 0 &&
796                 (sym2->usl.spillLoc == sym1))
797                 return TRUE ;
798         
799         return FALSE ;
800 }
801
802 /*-----------------------------------------------------------------*/
803 /* pic14_sameRegs - two asmops have the same registers             */
804 /*-----------------------------------------------------------------*/
805 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
806 {
807         int i;
808         
809         if (aop1 == aop2)
810                 return TRUE ;
811         
812         if (aop1->type != AOP_REG ||
813                 aop2->type != AOP_REG )
814                 return FALSE ;
815         
816         if (aop1->size != aop2->size )
817                 return FALSE ;
818         
819         for (i = 0 ; i < aop1->size ; i++ )
820                 if (aop1->aopu.aop_reg[i] !=
821                         aop2->aopu.aop_reg[i] )
822                         return FALSE ;
823                 
824                 return TRUE ;
825 }
826
827 /*-----------------------------------------------------------------*/
828 /* aopOp - allocates an asmop for an operand  :                    */
829 /*-----------------------------------------------------------------*/
830 void aopOp (operand *op, iCode *ic, bool result)
831 {
832         asmop *aop;
833         symbol *sym;
834         int i;
835         
836         if (!op)
837                 return ;
838         
839         /* if this a literal */
840         if (IS_OP_LITERAL(op)) {
841                 op->aop = aop = newAsmop(AOP_LIT);
842                 aop->aopu.aop_lit = op->operand.valOperand;
843                 aop->size = getSize(operandType(op));
844                 return;
845         }
846         
847         {
848                 sym_link *type = operandType(op);
849                 if(IS_PTR_CONST(type))
850                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
851         }
852         
853         /* if already has a asmop then continue */
854         if (op->aop)
855                 return ;
856         
857         /* if the underlying symbol has a aop */
858         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
859                 DEBUGpic14_emitcode(";","%d",__LINE__);
860                 op->aop = OP_SYMBOL(op)->aop;
861                 return;
862         }
863         
864         /* if this is a true symbol */
865         if (IS_TRUE_SYMOP(op)) {          
866                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
867                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
868                 return ;
869         }
870         
871         /* this is a temporary : this has
872         only four choices :
873         a) register
874         b) spillocation
875         c) rematerialize 
876         d) conditional   
877         e) can be a return use only */
878         
879         sym = OP_SYMBOL(op);
880         
881         
882         /* if the type is a conditional */
883         if (sym->regType == REG_CND) {
884                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
885                 aop->size = 0;
886                 return;
887         }
888         
889         /* if it is spilt then two situations
890         a) is rematerialize 
891         b) has a spill location */
892         if (sym->isspilt || sym->nRegs == 0) {
893                 
894                 DEBUGpic14_emitcode(";","%d",__LINE__);
895                 /* rematerialize it NOW */
896                 if (sym->remat) {
897                         
898                         sym->aop = op->aop = aop = aopForRemat (op);
899                         aop->size = getSize(sym->type);
900                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
901                         return;
902                 }
903                 
904 #if 0
905                 /* WREG is not usable as an ordinary operand with PIC architecture,
906                  * one might introduce a scratch register that can be used to make
907                  * WREG accesible as an operand... disable WREG for now */
908                 if (sym->accuse) {
909                         int i;
910                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
911                         aop->size = getSize(sym->type);
912                         for ( i = 0 ; i < 2 ; i++ )
913                                 aop->aopu.aop_str[i] = accUse[i];
914                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
915                         return;  
916                 }
917 #endif
918                 
919                 if (sym->ruonly ) {
920                         if(sym->isptr) {        // && sym->uptr 
921                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
922                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
923                                 
924                                 //PCOI(aop->aopu.pcop)->_const = 0;
925                                 //PCOI(aop->aopu.pcop)->index = 0;
926                                 /*
927                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
928                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
929                                 */
930                                 //allocDirReg (IC_LEFT(ic));
931                                 
932                                 aop->size = getSize(sym->type);
933                                 DEBUGpic14_emitcode(";","%d",__LINE__);
934                                 return;
935                                 
936                         } else {
937                                 
938                                 unsigned i;
939                                 
940                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
941                                 aop->size = getSize(sym->type);
942                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
943                                         aop->aopu.aop_str[i] = fReturn[i];
944                                 
945                                 DEBUGpic14_emitcode(";","%d",__LINE__);
946                                 return;
947                         }
948                 }
949                 
950                 /* else spill location  */
951                 if (sym->usl.spillLoc)
952                 {
953                         asmop *oldAsmOp = NULL;
954
955                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
956                         {
957                                 /* force a new aop if sizes differ */
958                                 oldAsmOp = sym->usl.spillLoc->aop;
959                                 sym->usl.spillLoc->aop = NULL;
960                         }
961                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
962                                 __FUNCTION__,__LINE__,
963                                 sym->usl.spillLoc->rname,
964                                 sym->rname, sym->usl.spillLoc->offset);
965                 
966                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
967                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
968                         {
969                                 /* Don't reuse the new aop, go with the last one */
970                                 sym->usl.spillLoc->aop = oldAsmOp;
971                         }
972                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
973                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
974                                 getSize(sym->type), 
975                                 sym->usl.spillLoc->offset);
976                         aop->size = getSize(sym->type);
977                 
978                         return;
979                 }
980         }
981         
982         {
983                 sym_link *type = operandType(op);
984                 if(IS_PTR_CONST(type)) 
985                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
986         }
987         
988         /* must be in a register */
989         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
990         sym->aop = op->aop = aop = newAsmop(AOP_REG);
991         aop->size = sym->nRegs;
992         for ( i = 0 ; i < sym->nRegs ;i++)
993                 aop->aopu.aop_reg[i] = sym->regs[i];
994 }
995
996 /*-----------------------------------------------------------------*/
997 /* freeAsmop - free up the asmop given to an operand                       */
998 /*----------------------------------------------------------------*/
999 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1000 {       
1001         asmop *aop ;
1002         
1003         if (!op)
1004                 aop = aaop;
1005         else 
1006                 aop = op->aop;
1007         
1008         if (!aop)
1009                 return ;
1010         
1011         if (aop->freed)
1012                 goto dealloc; 
1013         
1014         aop->freed = 1;
1015         
1016         /* depending on the asmop type only three cases need work AOP_RO
1017         , AOP_R1 && AOP_STK */
1018 #if 0
1019         switch (aop->type) {
1020         case AOP_R0 :
1021                 if (_G.r0Pushed ) {
1022                         if (pop) {
1023                                 pic14_emitcode ("pop","ar0");     
1024                                 _G.r0Pushed--;
1025                         }
1026                 }
1027                 bitVectUnSetBit(ic->rUsed,R0_IDX);
1028                 break;
1029                 
1030         case AOP_R1 :
1031                 if (_G.r1Pushed ) {
1032                         if (pop) {
1033                                 pic14_emitcode ("pop","ar1");
1034                                 _G.r1Pushed--;
1035                         }
1036                 }
1037                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
1038                 break;
1039                 
1040         case AOP_STK :
1041                 {
1042                         int sz = aop->size;      
1043                         int stk = aop->aopu.aop_stk + aop->size;
1044                         bitVectUnSetBit(ic->rUsed,R0_IDX);
1045                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
1046                         
1047                         getFreePtr(ic,&aop,FALSE);
1048                         
1049                         if (options.stack10bit)
1050                         {
1051                                 /* I'm not sure what to do here yet... */
1052                                 /* #STUB */
1053                                 fprintf(stderr, 
1054                                         "*** Warning: probably generating bad code for "
1055                                         "10 bit stack mode.\n");
1056                         }
1057                         
1058                         if (stk) {
1059                                 pic14_emitcode ("mov","a,_bp");
1060                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1061                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1062                         } else {
1063                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1064                         }
1065                         
1066                         while (sz--) {
1067                                 pic14_emitcode("pop","acc");
1068                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1069                                 if (!sz) break;
1070                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1071                         }
1072                         op->aop = aop;
1073                         freeAsmop(op,NULL,ic,TRUE);
1074                         if (_G.r0Pushed) {
1075                                 pic14_emitcode("pop","ar0");
1076                                 _G.r0Pushed--;
1077                         }
1078                         
1079                         if (_G.r1Pushed) {
1080                                 pic14_emitcode("pop","ar1");
1081                                 _G.r1Pushed--;
1082                         }         
1083                 }
1084         }
1085 #endif
1086         
1087 dealloc:
1088         /* all other cases just dealloc */
1089         if (op ) {
1090                 op->aop = NULL;
1091                 if (IS_SYMOP(op)) {
1092                         OP_SYMBOL(op)->aop = NULL;      
1093                         /* if the symbol has a spill */
1094                         if (SPIL_LOC(op))
1095                                 SPIL_LOC(op)->aop = NULL;
1096                 }
1097         }
1098 }
1099
1100 /*-----------------------------------------------------------------*/
1101 /* aopGet - for fetching value of the aop                                                  */
1102 /*-----------------------------------------------------------------*/
1103 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1104 {
1105         char *s = buffer ;
1106         char *rs;
1107         
1108         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1109         /* offset is greater than
1110         size then zero */
1111         if (offset > (aop->size - 1) &&
1112                 aop->type != AOP_LIT)
1113                 return zero;
1114         
1115         /* depending on type */
1116         switch (aop->type) {
1117                 
1118         case AOP_R0:
1119         case AOP_R1:
1120                 DEBUGpic14_emitcode(";","%d",__LINE__);
1121                 /* if we need to increment it */           
1122                 while (offset > aop->coff) {            
1123                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1124                         aop->coff++;
1125                 }
1126                 
1127                 while (offset < aop->coff) {
1128                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1129                         aop->coff--;
1130                 }
1131                 
1132                 aop->coff = offset ;
1133                 if (aop->paged) {
1134                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1135                         return (dname ? "acc" : "a");
1136                 }               
1137                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1138                 rs = Safe_calloc(1,strlen(s)+1);
1139                 strcpy(rs,s);   
1140                 return rs;
1141                 
1142         case AOP_DPTR:
1143         case AOP_DPTR2:
1144                 DEBUGpic14_emitcode(";","%d",__LINE__);
1145                 if (aop->type == AOP_DPTR2)
1146                 {
1147                         genSetDPTR(1);
1148                 }
1149                 
1150                 while (offset > aop->coff) {
1151                         pic14_emitcode ("inc","dptr");
1152                         aop->coff++;
1153                 }
1154                 
1155                 while (offset < aop->coff) {            
1156                         pic14_emitcode("lcall","__decdptr");
1157                         aop->coff--;
1158                 }
1159                 
1160                 aop->coff = offset;
1161                 if (aop->code) {
1162                         pic14_emitcode("clr","a");
1163                         pic14_emitcode("movc","a,@a+dptr");
1164                 }
1165                 else {
1166                         pic14_emitcode("movx","a,@dptr");
1167                 }
1168                 
1169                 if (aop->type == AOP_DPTR2)
1170                 {
1171                         genSetDPTR(0);
1172                 }
1173                 
1174                 return (dname ? "acc" : "a");
1175                 
1176                 
1177         case AOP_IMMD:
1178                 if (bit16) 
1179                         sprintf (s,"%s",aop->aopu.aop_immd);
1180                 else
1181                         if (offset) 
1182                                 sprintf(s,"(%s >> %d)",
1183                                 aop->aopu.aop_immd,
1184                                 offset*8);
1185                         else
1186                                 sprintf(s,"%s",
1187                                 aop->aopu.aop_immd);
1188                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1189                         rs = Safe_calloc(1,strlen(s)+1);
1190                         strcpy(rs,s);   
1191                         return rs;
1192                         
1193         case AOP_DIR:
1194                 if (offset) {
1195                         sprintf(s,"(%s + %d)",
1196                                 aop->aopu.aop_dir,
1197                                 offset);
1198                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1199                 } else
1200                         sprintf(s,"%s",aop->aopu.aop_dir);
1201                 rs = Safe_calloc(1,strlen(s)+1);
1202                 strcpy(rs,s);   
1203                 return rs;
1204                 
1205         case AOP_REG:
1206                 //if (dname) 
1207                 //        return aop->aopu.aop_reg[offset]->dname;
1208                 //else
1209                 return aop->aopu.aop_reg[offset]->name;
1210                 
1211         case AOP_CRY:
1212                 //pic14_emitcode(";","%d",__LINE__);
1213                 return aop->aopu.aop_dir;
1214                 
1215         case AOP_ACC:
1216                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1217                 return "AOP_accumulator_bug";
1218                 
1219         case AOP_LIT:
1220                 sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
1221                 rs = Safe_strdup(s);
1222                 return rs;
1223                 
1224         case AOP_STR:
1225                 aop->coff = offset ;
1226                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1227                         dname)
1228                         return "acc";
1229                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1230                 
1231                 return aop->aopu.aop_str[offset];
1232                 
1233         case AOP_PCODE:
1234                 {
1235                         pCodeOp *pcop = aop->aopu.pcop;
1236                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1237                         if(pcop->name) {
1238                                 if (offset) {
1239                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1240                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1241                                 } else {
1242                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1243                                         sprintf(s,"%s", pcop->name);
1244                                 }
1245                         } else
1246                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1247                         
1248                 }
1249                 rs = Safe_calloc(1,strlen(s)+1);
1250                 strcpy(rs,s);   
1251                 return rs;
1252                 
1253   }
1254   
1255   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1256           "aopget got unsupported aop->type");
1257   exit(0);
1258 }
1259
1260
1261 /*-----------------------------------------------------------------*/
1262 /* popGetTempReg - create a new temporary pCodeOp                                  */
1263 /*-----------------------------------------------------------------*/
1264 pCodeOp *popGetTempReg(void)
1265 {
1266         
1267         pCodeOp *pcop;
1268         
1269         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1270         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1271                 PCOR(pcop)->r->wasUsed=1;
1272                 PCOR(pcop)->r->isFree=0;
1273         }
1274         
1275         return pcop;
1276 }
1277
1278 /*-----------------------------------------------------------------*/
1279 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1280 /*-----------------------------------------------------------------*/
1281 void popReleaseTempReg(pCodeOp *pcop)
1282 {
1283         
1284         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1285                 PCOR(pcop)->r->isFree = 1;
1286         
1287 }
1288 /*-----------------------------------------------------------------*/
1289 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1290 /*-----------------------------------------------------------------*/
1291 pCodeOp *popGetLabel(unsigned int key)
1292 {
1293         
1294         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1295         
1296         if(key>(unsigned int)max_key)
1297                 max_key = key;
1298         
1299         return newpCodeOpLabel(NULL,key+100+labelOffset);
1300 }
1301
1302 /*-------------------------------------------------------------------*/
1303 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1304 /*-------------------------------------------------------------------*/
1305 pCodeOp *popGetHighLabel(unsigned int key)
1306 {
1307         pCodeOp *pcop;
1308         pcop = popGetLabel(key);
1309         PCOLAB(pcop)->offset = 1;
1310         return pcop;
1311 }
1312
1313 /*-----------------------------------------------------------------*/
1314 /* popGetLit - asm operator to pcode operator conversion                           */
1315 /*-----------------------------------------------------------------*/
1316 pCodeOp *popGetLit(unsigned int lit)
1317 {
1318         
1319         return newpCodeOpLit((unsigned char)lit);
1320 }
1321
1322 /*-----------------------------------------------------------------*/
1323 /* popGetImmd - asm operator to pcode immediate conversion                 */
1324 /*-----------------------------------------------------------------*/
1325 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1326 {
1327         
1328         return newpCodeOpImmd(name, offset,index, 0, is_func);
1329 }
1330
1331 extern set *externs;
1332
1333 /*-----------------------------------------------------------------*/
1334 /* popGetWithString - asm operator to pcode operator conversion                    */
1335 /*-----------------------------------------------------------------*/
1336 pCodeOp *popGetWithString(char *str, int isExtern)
1337 {
1338         pCodeOp *pcop;
1339         
1340         
1341         if(!str) {
1342                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1343                 exit (1);
1344         }
1345         
1346         pcop = newpCodeOp(str,PO_STR);
1347         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1348
1349         return pcop;
1350 }
1351
1352 pCodeOp *popGetExternal (char *str)
1353 {
1354         pCodeOp *pcop = popGetWithString (str, 1);
1355         
1356         if (str) {
1357           symbol *sym;
1358           bool found = 0;
1359
1360           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1361           {
1362             if (!strcmp (str, sym->rname))
1363               found = 1;
1364           }
1365           
1366           if (!found)
1367           {
1368             sym = newSymbol(str, 0);
1369             strncpy(sym->rname, str, SDCC_NAME_MAX);
1370             addSet (&externs, sym);
1371           } // if
1372         }
1373         return pcop;
1374 }
1375
1376 /*-----------------------------------------------------------------*/
1377 /* popRegFromString -                                                                                      */
1378 /*-----------------------------------------------------------------*/
1379 pCodeOp *popRegFromString(char *str, int size, int offset)
1380 {
1381         
1382         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1383         pcop->type = PO_DIR;
1384         
1385         DEBUGpic14_emitcode(";","%d",__LINE__);
1386         
1387         if(!str)
1388                 str = "BAD_STRING";
1389         
1390         pcop->name = Safe_calloc(1,strlen(str)+1);
1391         strcpy(pcop->name,str);
1392         
1393         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1394         
1395         PCOR(pcop)->r = dirregWithName(pcop->name);
1396         if(PCOR(pcop)->r == NULL) {
1397                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1398                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1399                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1400         } else {
1401                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1402         }
1403         PCOR(pcop)->instance = offset;
1404         
1405         return pcop;
1406 }
1407
1408 /*-----------------------------------------------------------------*/
1409 /*-----------------------------------------------------------------*/
1410 pCodeOp *popRegFromIdx(int rIdx)
1411 {
1412         pCodeOp *pcop;
1413         
1414         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1415                 __FUNCTION__,__LINE__,rIdx);
1416         
1417         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1418         
1419         PCOR(pcop)->rIdx = rIdx;
1420         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1421         PCOR(pcop)->r->isFree = 0;
1422         PCOR(pcop)->r->wasUsed = 1;
1423         
1424         pcop->type = PCOR(pcop)->r->pc_type;
1425         
1426         
1427         return pcop;
1428 }
1429
1430 /*-----------------------------------------------------------------*/
1431 /* popGet - asm operator to pcode operator conversion                      */
1432 /*-----------------------------------------------------------------*/
1433 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1434 {
1435         //char *s = buffer ;
1436         //char *rs;
1437         
1438         pCodeOp *pcop;
1439         
1440         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1441         /* offset is greater than
1442         size then zero */
1443
1444         assert (aop);
1445
1446
1447         /* XXX: still needed for BIT operands (AOP_CRY) */
1448         if (offset > (aop->size - 1) &&
1449                 aop->type != AOP_LIT &&
1450                 aop->type != AOP_PCODE)
1451         {
1452                 printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
1453                 return NULL;  //zero;
1454         }
1455         
1456         /* depending on type */
1457         switch (aop->type) {
1458                 
1459         case AOP_R0:
1460         case AOP_R1:
1461         case AOP_DPTR:
1462         case AOP_DPTR2:
1463         case AOP_ACC:
1464                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1465                 return NULL;
1466                 
1467         case AOP_IMMD:
1468                 DEBUGpic14_emitcode(";","%d",__LINE__);
1469                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1470                 
1471         case AOP_DIR:
1472                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1473 #if 0
1474                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1475                 pcop->type = PO_DIR;
1476                 
1477                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1478                 strcpy(pcop->name,aop->aopu.aop_dir);   
1479                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1480                 if(PCOR(pcop)->r == NULL) {
1481                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1482                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1483                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1484                 } else {
1485                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1486                 }
1487                 PCOR(pcop)->instance = offset;
1488                 
1489                 return pcop;
1490 #endif
1491                 
1492         case AOP_REG:
1493                 {
1494                         int rIdx;
1495                         assert (offset < aop->size);
1496                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1497                         
1498                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1499                         PCOR(pcop)->rIdx = rIdx;
1500                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1501                         PCOR(pcop)->r->wasUsed=1;
1502                         PCOR(pcop)->r->isFree=0;
1503                         
1504                         PCOR(pcop)->instance = offset;
1505                         pcop->type = PCOR(pcop)->r->pc_type;
1506                         //rs = aop->aopu.aop_reg[offset]->name;
1507                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1508                         return pcop;
1509                 }
1510                 
1511         case AOP_CRY:
1512                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1513                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1514                 //if(PCOR(pcop)->r == NULL)
1515                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1516                 return pcop;
1517                 
1518         case AOP_LIT:
1519                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1520                 
1521         case AOP_STR:
1522                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1523                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1524                 /*
1525                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1526                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1527                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1528                 pcop->type = PCOR(pcop)->r->pc_type;
1529                 pcop->name = PCOR(pcop)->r->name;
1530                 
1531                   return pcop;
1532                 */
1533                 
1534         case AOP_PCODE:
1535                 pcop = NULL;
1536                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1537                         __LINE__, 
1538                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1539                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1540                 switch (aop->aopu.pcop->type)
1541                 {
1542                 case PO_IMMEDIATE:
1543                   pcop = pCodeOpCopy (aop->aopu.pcop);
1544                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1545                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1546                   PCOI(pcop)->index += offset;
1547                   //PCOI(pcop)->offset = 0;
1548                   break;
1549                 case PO_DIR:
1550                   pcop = pCodeOpCopy (aop->aopu.pcop);
1551                   PCOR(pcop)->instance = offset;
1552                   break;
1553                 default:
1554                   assert ( !"unhandled pCode type" );
1555                   break;
1556                 } // switch
1557                 return pcop;
1558         }
1559         
1560         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1561                 "popGet got unsupported aop->type");
1562         exit(0);
1563 }
1564
1565 /*-----------------------------------------------------------------*/
1566 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1567 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1568 /*-----------------------------------------------------------------*/
1569 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1570 {
1571   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1572   {
1573     pCodeOp *pcop = aop->aopu.pcop;
1574     assert (offset <= GPTRSIZE);
1575
1576     /* special case: index >= 2 should return GPOINTER-style values */
1577     if (offset == 2)
1578     {
1579       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1580       return pcop;
1581     }
1582     
1583     pcop = pCodeOpCopy (pcop);
1584     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1585      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1586     PCOI(pcop)->offset += offset;
1587     PCOI(pcop)->index += index;
1588     //fprintf (stderr, "is PO_IMMEDIATE: %s+o%d+i%d (new o%d,i%d)\n", pcop->name,PCOI(pcop)->offset,PCOI(pcop)->index, offset, index);
1589     return pcop;
1590   } else {
1591     return popGet (aop, offset + index);
1592   }
1593 }
1594
1595 /*-----------------------------------------------------------------*/
1596 /* aopPut - puts a string for a aop                                                        */
1597 /*-----------------------------------------------------------------*/
1598 void aopPut (asmop *aop, char *s, int offset)
1599 {
1600         char *d = buffer ;
1601         symbol *lbl ;
1602         
1603         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1604         
1605         if (aop->size && offset > ( aop->size - 1)) {
1606                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1607                         "aopPut got offset > aop->size");
1608                 exit(0);
1609         }
1610         
1611         /* will assign value to value */
1612         /* depending on where it is ofcourse */
1613         switch (aop->type) {
1614         case AOP_DIR:
1615                 if (offset) {
1616                         sprintf(d,"(%s + %d)",
1617                                 aop->aopu.aop_dir,offset);
1618                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1619                         
1620                 } else
1621                         sprintf(d,"%s",aop->aopu.aop_dir);
1622                 
1623                 if (strcmp(d,s)) {
1624                         DEBUGpic14_emitcode(";","%d",__LINE__);
1625                         if(strcmp(s,"W"))
1626                                 pic14_emitcode("movf","%s,w",s);
1627                         pic14_emitcode("movwf","%s",d);
1628                         
1629                         if(strcmp(s,"W")) {
1630                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1631                                 if(offset >= aop->size) {
1632                                         emitpcode(POC_CLRF,popGet(aop,offset));
1633                                         break;
1634                                 } else {
1635                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1636                                 }
1637                         }
1638                         emitpcode(POC_MOVWF,popGet(aop,offset));
1639                 
1640                 }
1641                 break;
1642                 
1643         case AOP_REG:
1644                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1645                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1646                         /*
1647                         if (*s == '@'             ||
1648                         strcmp(s,"r0") == 0 ||
1649                         strcmp(s,"r1") == 0 ||
1650                         strcmp(s,"r2") == 0 ||
1651                         strcmp(s,"r3") == 0 ||
1652                         strcmp(s,"r4") == 0 ||
1653                         strcmp(s,"r5") == 0 ||
1654                         strcmp(s,"r6") == 0 || 
1655                         strcmp(s,"r7") == 0 )
1656                         pic14_emitcode("mov","%s,%s  ; %d",
1657                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1658                         else
1659                         */
1660                         
1661                         if(strcmp(s,"W")==0 )
1662                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1663                         
1664                         pic14_emitcode("movwf","%s",
1665                                 aop->aopu.aop_reg[offset]->name);
1666                         
1667                         if(strcmp(s,zero)==0) {
1668                                 emitpcode(POC_CLRF,popGet(aop,offset));
1669                                 
1670                         } else if(strcmp(s,"W")==0) {
1671                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1672                                 pcop->type = PO_GPR_REGISTER;
1673                                 
1674                                 PCOR(pcop)->rIdx = -1;
1675                                 PCOR(pcop)->r = NULL;
1676                                 
1677                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1678                                 pcop->name = Safe_strdup(s);
1679                                 emitpcode(POC_MOVFW,pcop);
1680                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1681                         } else if(strcmp(s,one)==0) {
1682                                 emitpcode(POC_CLRF,popGet(aop,offset));
1683                                 emitpcode(POC_INCF,popGet(aop,offset));
1684                         } else {
1685                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1686                         }
1687                 }
1688                 break;
1689                 
1690         case AOP_DPTR:
1691         case AOP_DPTR2:
1692                 
1693                 if (aop->type == AOP_DPTR2)
1694                 {
1695                         genSetDPTR(1);
1696                 }
1697                 
1698                 if (aop->code) {
1699                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1700                                 "aopPut writting to code space");
1701                         exit(0);
1702                 }
1703                 
1704                 while (offset > aop->coff) {
1705                         aop->coff++;
1706                         pic14_emitcode ("inc","dptr");
1707                 }
1708                 
1709                 while (offset < aop->coff) {
1710                         aop->coff-- ;
1711                         pic14_emitcode("lcall","__decdptr");
1712                 }
1713                 
1714                 aop->coff = offset;
1715                 
1716                 /* if not in accumulater */
1717                 MOVA(s);
1718                 
1719                 pic14_emitcode ("movx","@dptr,a");
1720                 
1721                 if (aop->type == AOP_DPTR2)
1722                 {
1723                         genSetDPTR(0);
1724                 }
1725                 break;
1726                 
1727         case AOP_R0:
1728         case AOP_R1:
1729                 while (offset > aop->coff) {
1730                         aop->coff++;
1731                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1732                 }
1733                 while (offset < aop->coff) {
1734                         aop->coff-- ;
1735                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1736                 }
1737                 aop->coff = offset;
1738                 
1739                 if (aop->paged) {
1740                         MOVA(s);                         
1741                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1742                         
1743                 } else
1744                         if (*s == '@') {
1745                                 MOVA(s);
1746                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1747                         } else
1748                                 if (strcmp(s,"r0") == 0 ||
1749                                         strcmp(s,"r1") == 0 ||
1750                                         strcmp(s,"r2") == 0 ||
1751                                         strcmp(s,"r3") == 0 ||
1752                                         strcmp(s,"r4") == 0 ||
1753                                         strcmp(s,"r5") == 0 ||
1754                                         strcmp(s,"r6") == 0 || 
1755                                         strcmp(s,"r7") == 0 ) {
1756                                         char buffer[10];
1757                                         sprintf(buffer,"a%s",s);
1758                                         pic14_emitcode("mov","@%s,%s",
1759                                                 aop->aopu.aop_ptr->name,buffer);
1760                                 } else
1761                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1762                                 
1763                                 break;
1764                                 
1765         case AOP_STK:
1766                 if (strcmp(s,"a") == 0)
1767                         pic14_emitcode("push","acc");
1768                 else
1769                         pic14_emitcode("push","%s",s);
1770                 
1771                 break;
1772                 
1773         case AOP_CRY:
1774                 /* if bit variable */
1775                 if (!aop->aopu.aop_dir) {
1776                         pic14_emitcode("clr","a");
1777                         pic14_emitcode("rlc","a");
1778                 } else {
1779                         if (s == zero) 
1780                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1781                         else
1782                                 if (s == one)
1783                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1784                                 else
1785                                         if (!strcmp(s,"c"))
1786                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1787                                         else {
1788                                                 lbl = newiTempLabel(NULL);
1789                                                 
1790                                                 if (strcmp(s,"a")) {
1791                                                         MOVA(s);
1792                                                 }
1793                                                 pic14_emitcode("clr","c");
1794                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1795                                                 pic14_emitcode("cpl","c");
1796                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1797                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1798                                         }
1799                 }
1800                 break;
1801                 
1802         case AOP_STR:
1803                 aop->coff = offset;
1804                 if (strcmp(aop->aopu.aop_str[offset],s))
1805                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1806                 break;
1807                 
1808         case AOP_ACC:
1809                 aop->coff = offset;
1810                 if (!offset && (strcmp(s,"acc") == 0))
1811                         break;
1812                 
1813                 if (strcmp(aop->aopu.aop_str[offset],s))
1814                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1815                 break;
1816                 
1817         default :
1818                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1819                         "aopPut got unsupported aop->type");
1820                 exit(0);
1821         }
1822         
1823 }
1824
1825 /*-----------------------------------------------------------------*/
1826 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1827 /*-----------------------------------------------------------------*/
1828 static void mov2w_op (operand *op, int offset)
1829 {
1830         assert (op);
1831         FENTRY;
1832
1833         /* for PO_IMMEDIATEs: use address or value? */
1834         if (op_isLitLike (op))
1835         {
1836                 /* access address of op */
1837                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1838                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1839                 {
1840                         if (offset == GPTRSIZE-1)
1841                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1842                         else
1843                                 emitpcode (POC_MOVLW, popGetLit (0));
1844                 }
1845                 else
1846                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1847         } else {
1848                 /* access value stored in op */
1849                 mov2w (AOP(op), offset);
1850         }
1851 }
1852
1853
1854 /*-----------------------------------------------------------------*/
1855 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1856 /*-----------------------------------------------------------------*/
1857 void mov2w (asmop *aop, int offset)
1858 {
1859         
1860         if(!aop)
1861                 return;
1862         
1863         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1864         
1865         if ( aop_isLitLike (aop) )
1866                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1867         else
1868                 emitpcode(POC_MOVFW,popGet(aop,offset));
1869         
1870 }
1871
1872 static void movwf (asmop *op, int offset)
1873 {
1874         emitpcode (POC_MOVWF, popGet(op, offset));
1875 }
1876
1877 static pCodeOp *get_argument_pcop (int idx)
1878 {
1879         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1880         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1881 }
1882
1883 static pCodeOp *get_return_val_pcop (int offset)
1884 {
1885         assert (offset > 0 && "the most significant byte is returned via WREG");
1886         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1887 }
1888
1889 static void pass_argument (operand *op, int offset, int idx)
1890 {
1891         if (op)
1892                 mov2w_op (op, offset);
1893         if (idx != 0)
1894                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1895 }
1896
1897 static void get_returnvalue (operand *op, int offset, int idx)
1898 {
1899         if (idx != 0)
1900                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1901         movwf(AOP(op), offset);
1902 }
1903
1904 static void call_libraryfunc (char *name)
1905 {
1906   /* library code might reside in different page... */
1907   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1908   /* call the library function */
1909   emitpcode (POC_CALL, popGetExternal (name));
1910   /* might return from different page... */
1911   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1912 }
1913 #if 0
1914 /*-----------------------------------------------------------------*/
1915 /* reAdjustPreg - points a register back to where it should        */
1916 /*-----------------------------------------------------------------*/
1917 static void reAdjustPreg (asmop *aop)
1918 {
1919         int size ;
1920         
1921         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1922         aop->coff = 0;
1923         if ((size = aop->size) <= 1)
1924                 return ;
1925         size-- ;
1926         switch (aop->type) {
1927         case AOP_R0 :
1928         case AOP_R1 :
1929                 while (size--)
1930                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1931                 break;                  
1932         case AOP_DPTR :
1933         case AOP_DPTR2:
1934                 if (aop->type == AOP_DPTR2)
1935                 {
1936                         genSetDPTR(1);
1937                 } 
1938                 while (size--)
1939                 {
1940                         pic14_emitcode("lcall","__decdptr");
1941                 }
1942                 
1943                 if (aop->type == AOP_DPTR2)
1944                 {
1945                         genSetDPTR(0);
1946                 }
1947                 break;
1948                 
1949         }
1950         
1951 }
1952 #endif
1953
1954
1955 #if 0
1956 /*-----------------------------------------------------------------*/
1957 /* opIsGptr: returns non-zero if the passed operand is             */
1958 /* a generic pointer type.                                         */
1959 /*-----------------------------------------------------------------*/ 
1960 static int opIsGptr(operand *op)
1961 {
1962         sym_link *type = operandType(op);
1963         
1964         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1965         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1966         {
1967                 return 1;
1968         }
1969         return 0;          
1970 }
1971 #endif
1972
1973 /*-----------------------------------------------------------------*/
1974 /* pic14_getDataSize - get the operand data size                   */
1975 /*-----------------------------------------------------------------*/
1976 int pic14_getDataSize(operand *op)
1977 {
1978         int size;
1979         
1980         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1981         
1982 #if 0
1983         size = getSize(OP_SYM_ETYPE(op));
1984         return size;
1985         //return AOP_SIZE(op);
1986         
1987         // tsd- in the pic port, the genptr size is 1, so this code here
1988         // fails. ( in the 8051 port, the size was 4).
1989 #else
1990         size = AOP_SIZE(op);
1991         if (IS_GENPTR(OP_SYM_TYPE(op)))
1992         {
1993                 sym_link *type = operandType(op);
1994                 if (IS_GENPTR(type))
1995                 {
1996                         /* generic pointer; arithmetic operations
1997                         * should ignore the high byte (pointer type).
1998                         */
1999                         size--;
2000                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2001                 }
2002         }
2003         return size;
2004 #endif
2005 }
2006
2007 /*-----------------------------------------------------------------*/
2008 /* pic14_outAcc - output Acc                                       */
2009 /*-----------------------------------------------------------------*/
2010 void pic14_outAcc(operand *result)
2011 {
2012         int size,offset;
2013         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2014         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2015         
2016         
2017         size = pic14_getDataSize(result);
2018         if(size){
2019                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2020                 size--;
2021                 offset = 1;
2022                 /* unsigned or positive */
2023                 while(size--)
2024                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2025         }
2026         
2027 }
2028
2029 /*-----------------------------------------------------------------*/
2030 /* pic14_outBitC - output a bit C                                  */
2031 /*-----------------------------------------------------------------*/
2032 void pic14_outBitC(operand *result)
2033 {
2034         
2035         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2036         /* if the result is bit */
2037         if (AOP_TYPE(result) == AOP_CRY) 
2038                 aopPut(AOP(result),"c",0);
2039         else {
2040                 pic14_emitcode("clr","a  ; %d", __LINE__);
2041                 pic14_emitcode("rlc","a");
2042                 pic14_outAcc(result);
2043         }
2044 }
2045
2046 /*-----------------------------------------------------------------*/
2047 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2048 /*-----------------------------------------------------------------*/
2049 void pic14_toBoolean(operand *oper)
2050 {
2051         int size = AOP_SIZE(oper);
2052         int offset = 0;
2053         
2054         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2055
2056         assert (size > 0);
2057
2058         if (size == 1) {
2059                 /* MOVFW does not load the flags... */
2060                 if (AOP_TYPE(oper) == AOP_ACC) {
2061                         emitpcode(POC_IORLW, popGetLit(0));
2062                         offset = 1;
2063                 } else {
2064                         emitpcode(POC_MOVLW, popGetLit(0));
2065                         offset = 0;
2066                 }
2067         } else {
2068                 if ( AOP_TYPE(oper) != AOP_ACC) {
2069                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2070                         offset = 1;
2071                 }
2072         }
2073         
2074         while (offset < size) {
2075                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2076         }
2077         /* Z is set iff (oper == 0) */
2078 }
2079
2080
2081 /*-----------------------------------------------------------------*/
2082 /* genNot - generate code for ! operation                          */
2083 /*-----------------------------------------------------------------*/
2084 static void genNot (iCode *ic)
2085 {
2086         //symbol *tlbl;
2087         int size;
2088
2089         FENTRY;
2090         
2091         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2092         /* assign asmOps to operand & result */
2093         aopOp (IC_LEFT(ic),ic,FALSE);
2094         aopOp (IC_RESULT(ic),ic,TRUE);
2095         
2096         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2097         /* if in bit space then a special case */
2098         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2099                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2100                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2101                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2102                 } else {
2103                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2104                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2105                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2106                 }
2107                 goto release;
2108         }
2109         
2110         size = AOP_SIZE(IC_LEFT(ic));
2111         mov2w (AOP(IC_LEFT(ic)),0);
2112         while (--size > 0)
2113         {
2114           if (op_isLitLike (IC_LEFT(ic)))
2115             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2116           else
2117             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2118         }
2119         emitpcode(POC_MOVLW, popGetLit (0));
2120         emitSKPNZ;
2121         emitpcode(POC_MOVLW, popGetLit (1));
2122         movwf(AOP(IC_RESULT(ic)), 0);
2123
2124         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2125         {
2126           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2127         }
2128         goto release;
2129         
2130 release:        
2131         /* release the aops */
2132         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2133         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2134 }
2135
2136
2137 /*-----------------------------------------------------------------*/
2138 /* genCpl - generate code for complement                                                   */
2139 /*-----------------------------------------------------------------*/
2140 static void genCpl (iCode *ic)
2141 {
2142         operand *left, *result;
2143         int size, offset=0;  
2144         
2145         FENTRY;
2146         
2147         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2148         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2149         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2150         
2151         /* if both are in bit space then 
2152         a special case */
2153         if (AOP_TYPE(result) == AOP_CRY &&
2154                 AOP_TYPE(left) == AOP_CRY ) { 
2155                 
2156                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2157                 pic14_emitcode("cpl","c"); 
2158                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2159                 goto release; 
2160         } 
2161         
2162         size = AOP_SIZE(result);
2163         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2164         while (size--) {
2165                 
2166                 if(AOP_TYPE(left) == AOP_ACC) 
2167                         emitpcode(POC_XORLW, popGetLit(0xff));
2168                 else
2169                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2170                 
2171                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2172                 offset++;
2173         }
2174         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2175         
2176         
2177 release:
2178         /* release the aops */
2179         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2180         freeAsmop(result,NULL,ic,TRUE);
2181 }
2182
2183 /*-----------------------------------------------------------------*/
2184 /* genUminusFloat - unary minus for floating points                        */
2185 /*-----------------------------------------------------------------*/
2186 static void genUminusFloat(operand *op,operand *result)
2187 {
2188         int size ,offset =0 ;
2189         char *l;
2190         
2191         FENTRY;
2192
2193         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2194         /* for this we just need to flip the 
2195         first it then copy the rest in place */
2196         size = AOP_SIZE(op) - 1;
2197         l = aopGet(AOP(op),3,FALSE,FALSE);
2198         
2199         MOVA(l);          
2200         
2201         pic14_emitcode("cpl","acc.7");
2202         aopPut(AOP(result),"a",3);      
2203         
2204         while(size--) {
2205                 aopPut(AOP(result),
2206                         aopGet(AOP(op),offset,FALSE,FALSE),
2207                         offset);
2208                 offset++;
2209         }                
2210 }
2211
2212 /*-----------------------------------------------------------------*/
2213 /* genUminus - unary minus code generation                                                 */
2214 /*-----------------------------------------------------------------*/
2215 static void genUminus (iCode *ic)
2216 {
2217         int size, i;
2218         sym_link *optype, *rtype;
2219         
2220         FENTRY;
2221         
2222         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2223         /* assign asmops */
2224         aopOp(IC_LEFT(ic),ic,FALSE);
2225         aopOp(IC_RESULT(ic),ic,TRUE);
2226         
2227         /* if both in bit space then special
2228         case */
2229         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2230                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2231                 
2232                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2233                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2234                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2235                 
2236                 goto release; 
2237         } 
2238         
2239         optype = operandType(IC_LEFT(ic));
2240         rtype = operandType(IC_RESULT(ic));
2241         
2242         /* if float then do float stuff */
2243         if (IS_FLOAT(optype)) {
2244                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2245                 goto release;
2246         }
2247         
2248         /* otherwise subtract from zero by taking the 2's complement */
2249         size = AOP_SIZE(IC_LEFT(ic));
2250         
2251         for(i=0; i<size; i++) {
2252                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2253                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2254                 else {
2255                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2256                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2257                 }
2258         }
2259         
2260         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2261         for(i=1; i<size; i++) {
2262                 emitSKPNZ;
2263                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2264         }
2265         
2266 release:
2267         /* release the aops */
2268         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2269         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2270 }
2271
2272 /*-----------------------------------------------------------------*/
2273 /* saveRegisters - will look for a call and save the registers     */
2274 /*-----------------------------------------------------------------*/
2275 static void saveRegisters(iCode *lic) 
2276 {
2277         int i;
2278         iCode *ic;
2279         bitVect *rsave;
2280         sym_link *dtype;
2281         
2282         FENTRY;
2283
2284         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2285         /* look for call */
2286         for (ic = lic ; ic ; ic = ic->next) 
2287                 if (ic->op == CALL || ic->op == PCALL)
2288                         break;
2289                 
2290                 if (!ic) {
2291                         fprintf(stderr,"found parameter push with no function call\n");
2292                         return ;
2293                 }
2294                 
2295                 /* if the registers have been saved already then
2296                 do nothing */
2297                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2298                         return ;
2299                 
2300                         /* find the registers in use at this time 
2301                 and push them away to safety */
2302                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2303                         ic->rUsed);
2304                 
2305                 ic->regsSaved = 1;
2306                 if (options.useXstack) {
2307                         if (bitVectBitValue(rsave,R0_IDX))
2308                                 pic14_emitcode("mov","b,r0");
2309                         pic14_emitcode("mov","r0,%s",spname);
2310                         for (i = 0 ; i < pic14_nRegs ; i++) {
2311                                 if (bitVectBitValue(rsave,i)) {
2312                                         if (i == R0_IDX)
2313                                                 pic14_emitcode("mov","a,b");
2314                                         else
2315                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2316                                         pic14_emitcode("movx","@r0,a");
2317                                         pic14_emitcode("inc","r0");
2318                                 }
2319                         }
2320                         pic14_emitcode("mov","%s,r0",spname);
2321                         if (bitVectBitValue(rsave,R0_IDX))
2322                                 pic14_emitcode("mov","r0,b");     
2323                 }// else
2324                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2325                 //        if (bitVectBitValue(rsave,i))
2326                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2327                 //}
2328                 
2329                 dtype = operandType(IC_LEFT(ic));
2330                 if (currFunc && dtype && 
2331                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2332                         IFFUNC_ISISR(currFunc->type) &&
2333                         !ic->bankSaved) 
2334                         
2335                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2336                 
2337 }
2338 /*-----------------------------------------------------------------*/
2339 /* unsaveRegisters - pop the pushed registers                                      */
2340 /*-----------------------------------------------------------------*/
2341 static void unsaveRegisters (iCode *ic)
2342 {
2343         int i;
2344         bitVect *rsave;
2345         
2346         FENTRY;
2347
2348         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2349         /* find the registers in use at this time 
2350         and push them away to safety */
2351         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2352                 ic->rUsed);
2353         
2354         if (options.useXstack) {
2355                 pic14_emitcode("mov","r0,%s",spname); 
2356                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2357                         if (bitVectBitValue(rsave,i)) {
2358                                 pic14_emitcode("dec","r0");
2359                                 pic14_emitcode("movx","a,@r0");
2360                                 if (i == R0_IDX)
2361                                         pic14_emitcode("mov","b,a");
2362                                 else
2363                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2364                         }       
2365                         
2366                 }
2367                 pic14_emitcode("mov","%s,r0",spname);
2368                 if (bitVectBitValue(rsave,R0_IDX))
2369                         pic14_emitcode("mov","r0,b");
2370         } //else
2371         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2372         //      if (bitVectBitValue(rsave,i))
2373         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2374         //}
2375         
2376 }  
2377
2378
2379 /*-----------------------------------------------------------------*/
2380 /* pushSide -                            */
2381 /*-----------------------------------------------------------------*/
2382 static void pushSide(operand * oper, int size)
2383 {
2384 #if 0
2385         int offset = 0;
2386         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2387         while (size--) {
2388                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2389                 if (AOP_TYPE(oper) != AOP_REG &&
2390                         AOP_TYPE(oper) != AOP_DIR &&
2391                         strcmp(l,"a") ) {
2392                         pic14_emitcode("mov","a,%s",l);
2393                         pic14_emitcode("push","acc");
2394                 } else
2395                         pic14_emitcode("push","%s",l);
2396         }
2397 #endif
2398 }
2399
2400 /*-----------------------------------------------------------------*/
2401 /* assignResultValue -                           */
2402 /*-----------------------------------------------------------------*/
2403 static void assignResultValue(operand * oper)
2404 {
2405         int size = AOP_SIZE(oper);
2406         int offset = 0;
2407         
2408         FENTRY;
2409
2410         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2411         
2412         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2413         
2414         /* assign MSB first (passed via WREG) */
2415         while (size--) {
2416                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2417                 GpsuedoStkPtr++;
2418         }
2419 }
2420
2421
2422 /*-----------------------------------------------------------------*/
2423 /* genIpush - genrate code for pushing this gets a little complex  */
2424 /*-----------------------------------------------------------------*/
2425 static void genIpush (iCode *ic)
2426 {
2427         FENTRY;
2428         
2429         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2430 #if 0
2431         int size, offset = 0 ;
2432         char *l;
2433         
2434         
2435         /* if this is not a parm push : ie. it is spill push 
2436         and spill push is always done on the local stack */
2437         if (!ic->parmPush) {
2438                 
2439                 /* and the item is spilt then do nothing */
2440                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2441                         return ;
2442                 
2443                 aopOp(IC_LEFT(ic),ic,FALSE);
2444                 size = AOP_SIZE(IC_LEFT(ic));
2445                 /* push it on the stack */
2446                 while(size--) {
2447                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2448                         if (*l == '#') {
2449                                 MOVA(l);
2450                                 l = "acc";
2451                         }
2452                         pic14_emitcode("push","%s",l);
2453                 }
2454                 return ;                
2455         }
2456         
2457         /* this is a paramter push: in this case we call
2458         the routine to find the call and save those
2459         registers that need to be saved */   
2460         saveRegisters(ic);
2461         
2462         /* then do the push */
2463         aopOp(IC_LEFT(ic),ic,FALSE);
2464         
2465         
2466         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2467         size = AOP_SIZE(IC_LEFT(ic));
2468         
2469         while (size--) {
2470                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2471                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2472                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2473                         strcmp(l,"a") ) {
2474                         pic14_emitcode("mov","a,%s",l);
2475                         pic14_emitcode("push","acc");
2476                 } else
2477                         pic14_emitcode("push","%s",l);
2478         }         
2479         
2480         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2481 #endif
2482 }
2483
2484 /*-----------------------------------------------------------------*/
2485 /* genIpop - recover the registers: can happen only for spilling   */
2486 /*-----------------------------------------------------------------*/
2487 static void genIpop (iCode *ic)
2488 {
2489         FENTRY;
2490
2491         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2492         assert (!"genIpop -- unimplemented");
2493 #if 0
2494         int size,offset ;
2495         
2496         
2497         /* if the temp was not pushed then */
2498         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2499                 return ;
2500         
2501         aopOp(IC_LEFT(ic),ic,FALSE);
2502         size = AOP_SIZE(IC_LEFT(ic));
2503         offset = (size-1);
2504         while (size--) 
2505                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2506                 FALSE,TRUE));
2507         
2508         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2509 #endif
2510 }
2511
2512 /*-----------------------------------------------------------------*/
2513 /* unsaverbank - restores the resgister bank from stack                    */
2514 /*-----------------------------------------------------------------*/
2515 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2516 {
2517         FENTRY;
2518
2519         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2520 #if 0
2521         int i;
2522         asmop *aop ;
2523         regs *r = NULL;
2524         
2525         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2526         if (popPsw) {
2527                 if (options.useXstack) {
2528                         aop = newAsmop(0);
2529                         r = getFreePtr(ic,&aop,FALSE);
2530                         
2531                         
2532                         pic14_emitcode("mov","%s,_spx",r->name);
2533                         pic14_emitcode("movx","a,@%s",r->name);
2534                         pic14_emitcode("mov","psw,a");
2535                         pic14_emitcode("dec","%s",r->name);
2536                         
2537                 }else
2538                         pic14_emitcode ("pop","psw");
2539         }
2540         
2541         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2542                 if (options.useXstack) {           
2543                         pic14_emitcode("movx","a,@%s",r->name);
2544                         //pic14_emitcode("mov","(%s+%d),a",
2545                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2546                         pic14_emitcode("dec","%s",r->name);
2547                         
2548                 } else 
2549                         pic14_emitcode("pop",""); //"(%s+%d)",
2550                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2551         }
2552         
2553         if (options.useXstack) {
2554                 
2555                 pic14_emitcode("mov","_spx,%s",r->name);
2556                 freeAsmop(NULL,aop,ic,TRUE);
2557                 
2558         }
2559 #endif 
2560 }
2561
2562 /*-----------------------------------------------------------------*/
2563 /* saverbank - saves an entire register bank on the stack                  */
2564 /*-----------------------------------------------------------------*/
2565 static void saverbank (int bank, iCode *ic, bool pushPsw)
2566 {
2567         FENTRY;
2568
2569         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2570 #if 0
2571         int i;
2572         asmop *aop ;
2573         regs *r = NULL;
2574         
2575         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2576         if (options.useXstack) {
2577                 
2578                 aop = newAsmop(0);
2579                 r = getFreePtr(ic,&aop,FALSE);  
2580                 pic14_emitcode("mov","%s,_spx",r->name);
2581                 
2582         }
2583         
2584         for (i = 0 ; i < pic14_nRegs ;i++) {
2585                 if (options.useXstack) {
2586                         pic14_emitcode("inc","%s",r->name);
2587                         //pic14_emitcode("mov","a,(%s+%d)",
2588                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2589                         pic14_emitcode("movx","@%s,a",r->name);                 
2590                 } else 
2591                         pic14_emitcode("push","");// "(%s+%d)",
2592                 //regspic14[i].base,8*bank+regspic14[i].offset);
2593         }
2594         
2595         if (pushPsw) {
2596                 if (options.useXstack) {
2597                         pic14_emitcode("mov","a,psw");
2598                         pic14_emitcode("movx","@%s,a",r->name); 
2599                         pic14_emitcode("inc","%s",r->name);
2600                         pic14_emitcode("mov","_spx,%s",r->name);                 
2601                         freeAsmop (NULL,aop,ic,TRUE);
2602                         
2603                 } else
2604                         pic14_emitcode("push","psw");
2605                 
2606                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2607         }
2608         ic->bankSaved = 1;
2609 #endif
2610 }
2611
2612 /*-----------------------------------------------------------------*/
2613 /* genCall - generates a call statement                                                    */
2614 /*-----------------------------------------------------------------*/
2615 static void genCall (iCode *ic)
2616 {
2617         sym_link *dtype;         
2618         symbol *sym;
2619         char *name;
2620         int isExtern;
2621         
2622         FENTRY;
2623
2624         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2625         
2626         /* if caller saves & we have not saved then */
2627         if (!ic->regsSaved)
2628                 saveRegisters(ic);
2629         
2630                 /* if we are calling a function that is not using
2631                 the same register bank then we need to save the
2632         destination registers on the stack */
2633         dtype = operandType(IC_LEFT(ic));
2634         if (currFunc && dtype && 
2635                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2636                 IFFUNC_ISISR(currFunc->type) &&
2637                 !ic->bankSaved) 
2638                 
2639                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2640         
2641         /* if send set is not empty the assign */
2642         if (_G.sendSet) {
2643                 iCode *sic;
2644                 /* For the Pic port, there is no data stack.
2645                 * So parameters passed to functions are stored
2646                 * in registers. (The pCode optimizer will get
2647                 * rid of most of these :).
2648                 */
2649                 int psuedoStkPtr=-1;
2650                 int firstTimeThruLoop = 1;
2651                 
2652                 _G.sendSet = reverseSet(_G.sendSet);
2653                 
2654                 /* First figure how many parameters are getting passed */
2655                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2656                 sic = setNextItem(_G.sendSet)) {
2657                         
2658                         aopOp(IC_LEFT(sic),sic,FALSE);
2659                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2660                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2661                 }
2662                 
2663                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2664                 sic = setNextItem(_G.sendSet)) {
2665                         int size, offset = 0;
2666                         
2667                         aopOp(IC_LEFT(sic),sic,FALSE);
2668                         size = AOP_SIZE(IC_LEFT(sic));
2669                         
2670                         while (size--) {
2671                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2672                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2673                                 
2674                                 if(!firstTimeThruLoop) {
2675                                         /* If this is not the first time we've been through the loop
2676                                         * then we need to save the parameter in a temporary
2677                                         * register. The last byte of the last parameter is
2678                                         * passed in W. */
2679                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2680                                         
2681                                 }
2682                                 firstTimeThruLoop=0;
2683                                 
2684                                 mov2w_op (IC_LEFT(sic),  offset);
2685                                 offset++;
2686                         }
2687                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2688                 }
2689                 _G.sendSet = NULL;
2690         }
2691         /* make the call */
2692         sym = OP_SYMBOL(IC_LEFT(ic));
2693         name = sym->rname[0] ? sym->rname : sym->name;
2694         isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
2695         if (isExtern) {
2696                 /* Extern functions and ISRs maybe on a different page;
2697                  * must call pagesel */
2698                 emitpcode(POC_PAGESEL,popGetWithString(name,1));
2699         }
2700         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2701         if (isExtern) {
2702                 /* May have returned from a different page;
2703                  * must use pagesel to restore PCLATH before next
2704                  * goto or call instruction */
2705                 emitpcode(POC_PAGESEL,popGetWithString("$",0));
2706         }
2707         GpsuedoStkPtr=0;
2708         /* if we need assign a result value */
2709         if ((IS_ITEMP(IC_RESULT(ic)) && 
2710                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2711                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2712                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2713                 
2714                 _G.accInUse++;
2715                 aopOp(IC_RESULT(ic),ic,FALSE);
2716                 _G.accInUse--;
2717                 
2718                 assignResultValue(IC_RESULT(ic));
2719                 
2720                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2721                         AopType(AOP_TYPE(IC_RESULT(ic))));
2722                 
2723                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2724         }
2725         
2726         /* if register bank was saved then pop them */
2727         if (ic->bankSaved)
2728                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2729         
2730         /* if we hade saved some registers then unsave them */
2731         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2732                 unsaveRegisters (ic);
2733         
2734         
2735 }
2736
2737 /*-----------------------------------------------------------------*/
2738 /* genPcall - generates a call by pointer statement                        */
2739 /*-----------------------------------------------------------------*/
2740 static void genPcall (iCode *ic)
2741 {
2742         sym_link *dtype;
2743         symbol *albl = newiTempLabel(NULL);
2744         symbol *blbl = newiTempLabel(NULL);
2745         PIC_OPCODE poc;
2746         pCodeOp *pcop;
2747         operand *left;
2748         
2749         FENTRY;
2750
2751         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2752         /* if caller saves & we have not saved then */
2753         if (!ic->regsSaved)
2754                 saveRegisters(ic);
2755         
2756                 /* if we are calling a function that is not using
2757                 the same register bank then we need to save the
2758         destination registers on the stack */
2759         dtype = operandType(IC_LEFT(ic));
2760         if (currFunc && dtype && 
2761                 IFFUNC_ISISR(currFunc->type) &&
2762                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2763                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2764         
2765         left = IC_LEFT(ic);
2766         aopOp(left,ic,FALSE);
2767         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2768         
2769         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2770         
2771         pushSide(IC_LEFT(ic), FPTRSIZE);
2772         
2773         /* if send set is not empty, assign parameters */
2774         if (_G.sendSet) {
2775                 
2776                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2777                 /* no way to pass args - W always gets used to make the call */
2778         }
2779         /* first idea - factor out a common helper function and call it.
2780         But don't know how to get it generated only once in its own block
2781         
2782         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2783                 char *rname;
2784                 char *buffer;
2785                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2786                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2787                 buffer = Safe_calloc(1,strlen(rname)+16);
2788                 sprintf(buffer, "%s_goto_helper", rname);
2789                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2790                 free(buffer);
2791         }
2792         */
2793         emitpcode(POC_CALL,popGetLabel(albl->key));
2794         pcop = popGetLabel(blbl->key);
2795         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2796         emitpcode(POC_GOTO,pcop);
2797         emitpLabel(albl->key);
2798         
2799         emitpcode(poc,popGetAddr(AOP(left),1,0));
2800         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2801         emitpcode(poc,popGetAddr(AOP(left),0,0));
2802         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2803         
2804         emitpLabel(blbl->key);
2805         
2806         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2807         
2808         /* if we need to assign a result value */
2809         if ((IS_ITEMP(IC_RESULT(ic)) &&
2810                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2811                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2812                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2813                 
2814                 _G.accInUse++;
2815                 aopOp(IC_RESULT(ic),ic,FALSE);
2816                 _G.accInUse--;
2817
2818                 GpsuedoStkPtr = 0;
2819                 
2820                 assignResultValue(IC_RESULT(ic));
2821                 
2822                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2823         }
2824         
2825         /* if register bank was saved then unsave them */
2826         if (currFunc && dtype && 
2827                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2828                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2829         
2830                 /* if we hade saved some registers then
2831         unsave them */
2832         if (ic->regsSaved)
2833                 unsaveRegisters (ic);
2834         
2835 }
2836
2837 /*-----------------------------------------------------------------*/
2838 /* resultRemat - result  is rematerializable                                       */
2839 /*-----------------------------------------------------------------*/
2840 static int resultRemat (iCode *ic)
2841 {
2842         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2843         FENTRY;
2844
2845         if (SKIP_IC(ic) || ic->op == IFX)
2846                 return 0;
2847         
2848         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2849                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2850                 if (sym->remat && !POINTER_SET(ic)) 
2851                         return 1;
2852         }
2853         
2854         return 0;
2855 }
2856
2857 #if defined(__BORLANDC__) || defined(_MSC_VER)
2858 #define STRCASECMP stricmp
2859 #else
2860 #define STRCASECMP strcasecmp
2861 #endif
2862
2863 #if 0
2864 /*-----------------------------------------------------------------*/
2865 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2866 /*-----------------------------------------------------------------*/
2867 static bool inExcludeList(char *s)
2868 {
2869         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2870         int i =0;
2871         
2872         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2873         if (options.excludeRegs[i] &&
2874                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2875                 return FALSE ;
2876         
2877         for ( i = 0 ; options.excludeRegs[i]; i++) {
2878                 if (options.excludeRegs[i] &&
2879                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2880                         return TRUE;
2881         }
2882         return FALSE ;
2883 }
2884 #endif
2885
2886 /*-----------------------------------------------------------------*/
2887 /* genFunction - generated code for function entry                                 */
2888 /*-----------------------------------------------------------------*/
2889 static void genFunction (iCode *ic)
2890 {
2891         symbol *sym;
2892         sym_link *ftype;
2893         
2894         FENTRY;
2895
2896         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2897         
2898         labelOffset += (max_key+4);
2899         max_key=0;
2900         GpsuedoStkPtr=0;
2901         _G.nRegsSaved = 0;
2902         /* create the function header */
2903         pic14_emitcode(";","-----------------------------------------");
2904         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2905         pic14_emitcode(";","-----------------------------------------");
2906         
2907         /* prevent this symbol from being emitted as 'extern' */
2908         pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
2909
2910         pic14_emitcode("","%s:",sym->rname);
2911         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2912         
2913         ftype = operandType(IC_LEFT(ic));
2914         
2915         /* if critical function then turn interrupts off */
2916         if (IFFUNC_ISCRITICAL(ftype))
2917                 pic14_emitcode("clr","ea");
2918         
2919                 /* here we need to generate the equates for the
2920         register bank if required */
2921 #if 0
2922         if (FUNC_REGBANK(ftype) != rbank) {
2923                 int i ;
2924                 
2925                 rbank = FUNC_REGBANK(ftype);
2926                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2927                         if (strcmp(regspic14[i].base,"0") == 0)
2928                                 pic14_emitcode("","%s = 0x%02x",
2929                                 regspic14[i].dname,
2930                                 8*rbank+regspic14[i].offset);
2931                         else
2932                                 pic14_emitcode ("","%s = %s + 0x%02x",
2933                                 regspic14[i].dname,
2934                                 regspic14[i].base,
2935                                 8*rbank+regspic14[i].offset);
2936                 }
2937         }
2938 #endif
2939         
2940         /* if this is an interrupt service routine */
2941         pic14_inISR = 0;
2942         if (IFFUNC_ISISR(sym->type)) {
2943                 pic14_inISR = 1;
2944         /*  already done in pic14createInterruptVect() - delete me
2945         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2946         emitpcodeNULLop(POC_NOP);
2947         emitpcodeNULLop(POC_NOP);
2948         emitpcodeNULLop(POC_NOP);
2949                 */
2950                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2951                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2952                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2953                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2954                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2955                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2956                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2957                 
2958                 pBlockConvert2ISR(pb);
2959                 pic14_hasInterrupt = 1;
2960 #if 0  
2961                 if (!inExcludeList("acc"))              
2962                         pic14_emitcode ("push","acc");  
2963                 if (!inExcludeList("b"))
2964                         pic14_emitcode ("push","b");
2965                 if (!inExcludeList("dpl"))
2966                         pic14_emitcode ("push","dpl");
2967                 if (!inExcludeList("dph"))
2968                         pic14_emitcode ("push","dph");
2969                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2970                 {
2971                         pic14_emitcode ("push", "dpx");
2972                         /* Make sure we're using standard DPTR */
2973                         pic14_emitcode ("push", "dps");
2974                         pic14_emitcode ("mov", "dps, #0x00");
2975                         if (options.stack10bit)
2976                         { 
2977                                 /* This ISR could conceivably use DPTR2. Better save it. */
2978                                 pic14_emitcode ("push", "dpl1");
2979                                 pic14_emitcode ("push", "dph1");
2980                                 pic14_emitcode ("push", "dpx1");
2981                         }
2982                 }
2983                 /* if this isr has no bank i.e. is going to
2984                 run with bank 0 , then we need to save more
2985                 registers :-) */
2986                 if (!FUNC_REGBANK(sym->type)) {
2987                         
2988                 /* if this function does not call any other
2989                 function then we can be economical and
2990                         save only those registers that are used */
2991                         if (! IFFUNC_HASFCALL(sym->type)) {
2992                                 int i;
2993                                 
2994                                 /* if any registers used */
2995                                 if (sym->regsUsed) {
2996                                         /* save the registers used */
2997                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2998                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2999                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3000                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
3001                                         }
3002                                 }
3003                                 
3004                         } else {
3005                         /* this function has    a function call cannot
3006                         determines register usage so we will have the
3007                                 entire bank */
3008                                 saverbank(0,ic,FALSE);
3009                         }       
3010                 }
3011 #endif
3012         } else {
3013         /* if callee-save to be used for this function
3014                 then save the registers being used in this function */
3015                 if (IFFUNC_CALLEESAVES(sym->type)) {
3016                         int i;
3017                         
3018                         /* if any registers used */
3019                         if (sym->regsUsed) {
3020                                 /* save the registers used */
3021                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3022                                         if (bitVectBitValue(sym->regsUsed,i) ||
3023                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3024                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3025                                                 _G.nRegsSaved++;
3026                                         }
3027                                 }
3028                         }
3029                 }
3030         }
3031         
3032         /* set the register bank to the desired value */
3033         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3034                 pic14_emitcode("push","psw");
3035                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3036         }
3037         
3038         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3039                 
3040                 if (options.useXstack) {
3041                         pic14_emitcode("mov","r0,%s",spname);
3042                         pic14_emitcode("mov","a,_bp");
3043                         pic14_emitcode("movx","@r0,a");
3044                         pic14_emitcode("inc","%s",spname);
3045                 }
3046                 else
3047                 {
3048                         /* set up the stack */
3049                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3050                 }
3051                 pic14_emitcode ("mov","_bp,%s",spname);
3052         }
3053         
3054         /* adjust the stack for the function */
3055         if (sym->stack) {
3056                 
3057                 int i = sym->stack;
3058                 if (i > 256 ) 
3059                         werror(W_STACK_OVERFLOW,sym->name);
3060                 
3061                 if (i > 3 && sym->recvSize < 4) {                
3062                         
3063                         pic14_emitcode ("mov","a,sp");
3064                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3065                         pic14_emitcode ("mov","sp,a");
3066                         
3067                 }
3068                 else
3069                         while(i--)
3070                                 pic14_emitcode("inc","sp");
3071         }
3072         
3073         if (sym->xstack) {
3074                 
3075                 pic14_emitcode ("mov","a,_spx");
3076                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3077                 pic14_emitcode ("mov","_spx,a");
3078         }
3079         
3080 }
3081
3082 /*-----------------------------------------------------------------*/
3083 /* genEndFunction - generates epilogue for functions                       */
3084 /*-----------------------------------------------------------------*/
3085 static void genEndFunction (iCode *ic)
3086 {
3087         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3088         
3089         FENTRY;
3090
3091         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3092         
3093         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3094         {
3095                 pic14_emitcode ("mov","%s,_bp",spname);
3096         }
3097         
3098         /* if use external stack but some variables were
3099         added to the local stack then decrement the
3100         local stack */
3101         if (options.useXstack && sym->stack) {    
3102                 pic14_emitcode("mov","a,sp");
3103                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3104                 pic14_emitcode("mov","sp,a");
3105         }
3106         
3107         
3108         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3109                 if (options.useXstack) {
3110                         pic14_emitcode("mov","r0,%s",spname);
3111                         pic14_emitcode("movx","a,@r0");
3112                         pic14_emitcode("mov","_bp,a");
3113                         pic14_emitcode("dec","%s",spname);
3114                 }
3115                 else
3116                 {
3117                         pic14_emitcode ("pop","_bp");
3118                 }
3119         }
3120         
3121         /* restore the register bank    */        
3122         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3123                 pic14_emitcode ("pop","psw");
3124         
3125         if (IFFUNC_ISISR(sym->type)) {
3126                 
3127                 /* now we need to restore the registers */
3128                 /* if this isr has no bank i.e. is going to
3129                 run with bank 0 , then we need to save more
3130 registers :-) */
3131                 if (!FUNC_REGBANK(sym->type)) {
3132                         
3133                 /* if this function does not call any other
3134                 function then we can be economical and
3135                         save only those registers that are used */
3136                         if (! IFFUNC_HASFCALL(sym->type)) {
3137                                 int i;
3138                                 
3139                                 /* if any registers used */
3140                                 if (sym->regsUsed) {
3141                                         /* save the registers used */
3142                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3143                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3144                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3145                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3146                                         }
3147                                 }
3148                                 
3149                         } else {
3150                         /* this function has    a function call cannot
3151                         determines register usage so we will have the
3152                                 entire bank */
3153                                 unsaverbank(0,ic,FALSE);
3154                         }       
3155                 }
3156 #if 0
3157                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3158                 {
3159                         if (options.stack10bit)
3160                         {
3161                                 pic14_emitcode ("pop", "dpx1");
3162                                 pic14_emitcode ("pop", "dph1");
3163                                 pic14_emitcode ("pop", "dpl1");
3164                         } 
3165                         pic14_emitcode ("pop", "dps");
3166                         pic14_emitcode ("pop", "dpx");
3167                 }
3168                 if (!inExcludeList("dph"))
3169                         pic14_emitcode ("pop","dph");
3170                 if (!inExcludeList("dpl"))
3171                         pic14_emitcode ("pop","dpl");
3172                 if (!inExcludeList("b"))
3173                         pic14_emitcode ("pop","b");
3174                 if (!inExcludeList("acc"))
3175                         pic14_emitcode ("pop","acc");
3176                 
3177                 if (IFFUNC_ISCRITICAL(sym->type))
3178                         pic14_emitcode("setb","ea");
3179 #endif
3180                 
3181                 /* if debug then send end of function */
3182                 /*      if (options.debug && currFunc) { */
3183                 if (currFunc) {
3184                         debugFile->writeEndFunction (currFunc, ic, 1);
3185                 }
3186                 
3187                 pic14_emitcode ("reti","");
3188                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3189                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3190                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3191                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3192                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3193                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3194                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3195                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3196                 emitpcodeNULLop(POC_RETFIE);
3197         }
3198         else {
3199                 if (IFFUNC_ISCRITICAL(sym->type))
3200                         pic14_emitcode("setb","ea");
3201                 
3202                 if (IFFUNC_CALLEESAVES(sym->type)) {
3203                         int i;
3204                         
3205                         /* if any registers used */
3206                         if (sym->regsUsed) {
3207                                 /* save the registers used */
3208                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3209                                         if (bitVectBitValue(sym->regsUsed,i) ||
3210                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3211                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3212                                 }
3213                         }
3214                         
3215                 }
3216                 
3217                 /* if debug then send end of function */
3218                 if (currFunc) {
3219                         debugFile->writeEndFunction (currFunc, ic, 1);
3220                 }
3221                 
3222                 pic14_emitcode ("return","");
3223                 emitpcodeNULLop(POC_RETURN);
3224                 
3225                 /* Mark the end of a function */
3226                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3227         }
3228         
3229 }
3230
3231 /*-----------------------------------------------------------------*/
3232 /* genRet - generate code for return statement                                     */
3233 /*-----------------------------------------------------------------*/
3234 static void genRet (iCode *ic)
3235 {
3236         int size,offset = 0;
3237         
3238         FENTRY;
3239
3240         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3241         /* if we have no return value then
3242         just generate the "ret" */
3243         if (!IC_LEFT(ic)) 
3244                 goto jumpret;           
3245         
3246                 /* we have something to return then
3247         move the return value into place */
3248         aopOp(IC_LEFT(ic),ic,FALSE);
3249         size = AOP_SIZE(IC_LEFT(ic));
3250
3251         for (offset = 0; offset < size; offset++)
3252         {
3253                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3254         }
3255         
3256         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3257         
3258 jumpret:
3259         /* generate a jump to the return label
3260         if the next is not the return statement */
3261         if (!(ic->next && ic->next->op == LABEL &&
3262                 IC_LABEL(ic->next) == returnLabel)) {
3263                 
3264                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3265         }
3266         
3267 }
3268
3269 /*-----------------------------------------------------------------*/
3270 /* genLabel - generates a label                                                                    */
3271 /*-----------------------------------------------------------------*/
3272 static void genLabel (iCode *ic)
3273 {
3274         FENTRY;
3275
3276         /* special case never generate */
3277         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3278         if (IC_LABEL(ic) == entryLabel)
3279                 return ;
3280         
3281         emitpLabel(IC_LABEL(ic)->key);
3282         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3283 }
3284
3285 /*-----------------------------------------------------------------*/
3286 /* genGoto - generates a goto                                                                      */
3287 /*-----------------------------------------------------------------*/
3288 //tsd
3289 static void genGoto (iCode *ic)
3290 {
3291         FENTRY;
3292
3293         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3294         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3295 }
3296
3297
3298 /*-----------------------------------------------------------------*/
3299 /* genMultbits :- multiplication of bits                                                   */
3300 /*-----------------------------------------------------------------*/
3301 static void genMultbits (operand *left, 
3302                                                  operand *right, 
3303                                                  operand *result)
3304 {
3305         FENTRY;
3306         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3307         
3308         if(!pic14_sameRegs(AOP(result),AOP(right)))
3309                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3310         
3311         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3312         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3313         emitpcode(POC_BCF,  popGet(AOP(result),0));
3314         
3315 }
3316
3317
3318 /*-----------------------------------------------------------------*/
3319 /* genMultOneByte : 8 bit multiplication & division                        */
3320 /*-----------------------------------------------------------------*/
3321 static void genMultOneByte (operand *left,
3322                                                         operand *right,
3323                                                         operand *result)
3324 {
3325         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3326         
3327         // symbol *lbl ;
3328         int size,offset,i;
3329         
3330         
3331         FENTRY;
3332         
3333         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3334         DEBUGpic14_AopType(__LINE__,left,right,result);
3335         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3336         
3337         /* (if two literals, the value is computed before) */
3338         /* if one literal, literal on the right */
3339         if (AOP_TYPE(left) == AOP_LIT){
3340                 operand *t = right;
3341                 right = left;
3342                 left = t;
3343         }
3344
3345         assert (AOP_SIZE(left) == AOP_SIZE(right));
3346         
3347         size = min(AOP_SIZE(result),AOP_SIZE(left));
3348         offset = Gstack_base_addr - (2*size - 1);
3349
3350         /* pass right operand as argument */
3351         for (i=0; i < size; i++)
3352         {
3353                 mov2w (AOP(right), i);
3354                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3355         } // for
3356         
3357         /* pass left operand as argument */
3358         for (i=0; i < size; i++)
3359         {
3360                 mov2w (AOP(left), i);
3361                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3362         } // for
3363         assert (offset == Gstack_base_addr);
3364         
3365         /* call library routine */
3366         assert (size > 0 && size <= 4);
3367         call_libraryfunc (func[size]);
3368         
3369         /* assign result */
3370         movwf (AOP(result), size-1);
3371         for (i=0; i < size - 1; i++)
3372         {
3373                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3374                 movwf (AOP(result), size - 2 - i);
3375         } // for
3376
3377         /* now (zero-/sign) extend the result to its size */
3378         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3379 }
3380
3381 /*-----------------------------------------------------------------*/
3382 /* genMult - generates code for multiplication                                     */
3383 /*-----------------------------------------------------------------*/
3384 static void genMult (iCode *ic)
3385 {
3386         operand *left = IC_LEFT(ic);
3387         operand *right = IC_RIGHT(ic);
3388         operand *result= IC_RESULT(ic); 
3389         
3390         FENTRY;
3391
3392         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3393         /* assign the amsops */
3394         aopOp (left,ic,FALSE);
3395         aopOp (right,ic,FALSE);
3396         aopOp (result,ic,TRUE);
3397         
3398         DEBUGpic14_AopType(__LINE__,left,right,result);
3399         
3400         /* special cases first */
3401         /* both are bits */
3402         if (AOP_TYPE(left) == AOP_CRY &&
3403                 AOP_TYPE(right)== AOP_CRY) {
3404                 genMultbits(left,right,result);
3405                 goto release ;
3406         }
3407         
3408         /* if both are of size == 1 */
3409         if (AOP_SIZE(left) == 1 &&
3410                 AOP_SIZE(right) == 1 ) {
3411                 genMultOneByte(left,right,result);
3412                 goto release ;
3413         }
3414         
3415         /* should have been converted to function call */
3416         assert(0) ;
3417         
3418 release :
3419         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3420         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3421         freeAsmop(result,NULL,ic,TRUE); 
3422 }
3423
3424 /*-----------------------------------------------------------------*/
3425 /* genDivbits :- division of bits                                                                  */
3426 /*-----------------------------------------------------------------*/
3427 static void genDivbits (operand *left, 
3428                                                 operand *right, 
3429                                                 operand *result)
3430 {
3431         
3432         char *l;
3433         
3434         FENTRY;
3435
3436         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3437         /* the result must be bit */      
3438         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3439         l = aopGet(AOP(left),0,FALSE,FALSE);
3440         
3441         MOVA(l);          
3442         
3443         pic14_emitcode("div","ab");
3444         pic14_emitcode("rrc","a");
3445         aopPut(AOP(result),"c",0);
3446 }
3447
3448 /*-----------------------------------------------------------------*/
3449 /* genDivOneByte : 8 bit division                                                                  */
3450 /*-----------------------------------------------------------------*/
3451 static void genDivOneByte (operand *left,
3452                                                    operand *right,
3453                                                    operand *result)
3454 {
3455         int size;
3456         
3457         FENTRY;
3458         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3459         
3460         assert (AOP_SIZE(result) == 1);
3461         assert (AOP_SIZE(right) == 1);
3462         assert (AOP_SIZE(left) == 1);
3463
3464         size = min(AOP_SIZE(result),AOP_SIZE(left));
3465
3466         if (AOP_TYPE(right) == AOP_LIT)
3467         {
3468                 /* XXX: might add specialized code */
3469         }
3470
3471         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3472         {
3473                 /* unsigned division */
3474         #if 1
3475                 mov2w(AOP(right),0);
3476                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3477                 mov2w(AOP(left),0);
3478                 call_libraryfunc("__divuchar");
3479                 movwf(AOP(result),0);
3480         #else
3481                 pCodeOp *temp;
3482                 symbol *lbl;
3483
3484                 temp = popGetTempReg();
3485                 lbl = newiTempLabel(NULL);
3486                 
3487                 /* XXX: improve this naive approach:
3488                    [result] = [a] / [b]
3489                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3490
3491                    In PIC assembler:
3492                    movf  left,W
3493                    movwf temp           // temp <-- left
3494                    movf  right,W        // W <-- right
3495                    clrf  result
3496                    label1:
3497                    incf  result
3498                    subwf temp,F         // temp <-- temp - W
3499                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3500                    goto  label1
3501                    decf result          // we just subtract once too often
3502                  */
3503
3504                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3505                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3506                 
3507                 mov2w(AOP(left),0);
3508                 emitpcode(POC_MOVWF, temp);
3509                 mov2w(AOP(right),0);
3510                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3511
3512                 emitpLabel(lbl->key);
3513                 emitpcode(POC_INCF, popGet(AOP(result),0));
3514                 emitpcode(POC_SUBWF, temp);
3515                 emitSKPNC;
3516                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3517                 emitpcode(POC_DECF, popGet(AOP(result),0));
3518         #endif
3519         }
3520         else
3521         {
3522                 /* signed division */
3523                 mov2w(AOP(right),0);
3524                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3525                 mov2w(AOP(left),0);
3526                 call_libraryfunc("__divschar");
3527                 movwf(AOP(result),0);
3528         }
3529
3530         /* now performed the signed/unsigned division -- extend result */
3531         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3532 }
3533
3534 /*-----------------------------------------------------------------*/
3535 /* genDiv - generates code for division                            */
3536 /*-----------------------------------------------------------------*/
3537 static void genDiv (iCode *ic)
3538 {
3539         operand *left = IC_LEFT(ic);
3540         operand *right = IC_RIGHT(ic);
3541         operand *result= IC_RESULT(ic); 
3542         
3543         FENTRY;
3544         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3545         /* assign the amsops */
3546         aopOp (left,ic,FALSE);
3547         aopOp (right,ic,FALSE);
3548         aopOp (result,ic,TRUE);
3549         
3550         /* special cases first */
3551         /* both are bits */
3552         if (AOP_TYPE(left) == AOP_CRY &&
3553                 AOP_TYPE(right)== AOP_CRY) {
3554                 genDivbits(left,right,result);
3555                 goto release ;
3556         }
3557         
3558         /* if both are of size == 1 */
3559         if (AOP_SIZE(left) == 1 &&
3560                 AOP_SIZE(right) == 1 ) {
3561                 genDivOneByte(left,right,result);
3562                 goto release ;
3563         }
3564         
3565         /* should have been converted to function call */
3566         assert(0);
3567 release :
3568         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3569         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3570         freeAsmop(result,NULL,ic,TRUE); 
3571 }
3572
3573 /*-----------------------------------------------------------------*/
3574 /* genModbits :- modulus of bits                                                                   */
3575 /*-----------------------------------------------------------------*/
3576 static void genModbits (operand *left, 
3577                                                 operand *right, 
3578                                                 operand *result)
3579 {
3580         
3581         char *l;
3582         
3583         FENTRY;
3584         /* the result must be bit */      
3585         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3586         l = aopGet(AOP(left),0,FALSE,FALSE);
3587         
3588         MOVA(l);
3589         
3590         pic14_emitcode("div","ab");
3591         pic14_emitcode("mov","a,b");
3592         pic14_emitcode("rrc","a");
3593         aopPut(AOP(result),"c",0);
3594 }
3595
3596 /*-----------------------------------------------------------------*/
3597 /* genModOneByte : 8 bit modulus                                                                   */
3598 /*-----------------------------------------------------------------*/
3599 static void genModOneByte (operand *left,
3600                                                    operand *right,
3601                                                    operand *result)
3602 {
3603         int size;
3604         
3605         FENTRY;
3606         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3607         
3608         assert (AOP_SIZE(result) == 1);
3609         assert (AOP_SIZE(right) == 1);
3610         assert (AOP_SIZE(left) == 1);
3611
3612         size = min(AOP_SIZE(result),AOP_SIZE(left));
3613
3614         if (AOP_TYPE(right) == AOP_LIT)
3615         {
3616                 /* XXX: might add specialized code */
3617         }
3618
3619         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3620         {
3621                 /* unsigned division */
3622         #if 1
3623                 mov2w(AOP(right),0);
3624                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3625                 mov2w(AOP(left),0);
3626                 call_libraryfunc("__moduchar");
3627                 movwf(AOP(result),0);
3628         #else
3629                 pCodeOp *temp;
3630                 symbol *lbl;
3631
3632                 lbl = newiTempLabel(NULL);
3633                 
3634                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3635
3636                 /* XXX: improve this naive approach:
3637                    [result] = [a] % [b]
3638                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3639
3640                    In PIC assembler:
3641                    movf  left,W
3642                    movwf result         // result <-- left
3643                    movf  right,W        // W <-- right
3644                    label1:
3645                    subwf result,F       // result <-- result - W
3646                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3647                    goto  label1
3648                    addwf result, F      // we just subtract once too often
3649                  */
3650
3651                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3652                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3653                 
3654                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3655                 {
3656                         mov2w(AOP(left),0);
3657                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3658                 }
3659                 mov2w(AOP(right),0);
3660
3661                 emitpLabel(lbl->key);
3662                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3663                 emitSKPNC;
3664                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3665                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3666         #endif
3667         }
3668         else
3669         {
3670                 /* signed division */
3671                 mov2w(AOP(right),0);
3672                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3673                 mov2w(AOP(left),0);
3674                 call_libraryfunc("__modschar");
3675                 movwf(AOP(result),0);
3676         }
3677
3678         /* now we performed the signed/unsigned modulus -- extend result */
3679         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3680 }
3681
3682 /*-----------------------------------------------------------------*/
3683 /* genMod - generates code for division                                                    */
3684 /*-----------------------------------------------------------------*/
3685 static void genMod (iCode *ic)
3686 {
3687         operand *left = IC_LEFT(ic);
3688         operand *right = IC_RIGHT(ic);
3689         operand *result= IC_RESULT(ic);  
3690         
3691         FENTRY;
3692         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3693         /* assign the amsops */
3694         aopOp (left,ic,FALSE);
3695         aopOp (right,ic,FALSE);
3696         aopOp (result,ic,TRUE);
3697         
3698         /* special cases first */
3699         /* both are bits */
3700         if (AOP_TYPE(left) == AOP_CRY &&
3701                 AOP_TYPE(right)== AOP_CRY) {
3702                 genModbits(left,right,result);
3703                 goto release ;
3704         }
3705         
3706         /* if both are of size == 1 */
3707         if (AOP_SIZE(left) == 1 &&
3708                 AOP_SIZE(right) == 1 ) {
3709                 genModOneByte(left,right,result);
3710                 goto release ;
3711         }
3712         
3713         /* should have been converted to function call */
3714         assert(0);
3715         
3716 release :
3717         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3718         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3719         freeAsmop(result,NULL,ic,TRUE); 
3720 }
3721
3722 /*-----------------------------------------------------------------*/
3723 /* genIfxJump :- will create a jump depending on the ifx                   */
3724 /*-----------------------------------------------------------------*/
3725 /*
3726 note: May need to add parameter to indicate when a variable is in bit space.
3727 */
3728 static void genIfxJump (iCode *ic, char *jval)
3729 {
3730         
3731         FENTRY;
3732         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3733         /* if true label then we jump if condition
3734         supplied is true */
3735         if ( IC_TRUE(ic) ) {
3736                 
3737                 if(strcmp(jval,"a") == 0)
3738                         emitSKPZ;
3739                 else if (strcmp(jval,"c") == 0)
3740                         emitSKPC;
3741                 else {
3742                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3743                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3744                 }
3745                 
3746                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3747                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3748                 
3749         }
3750         else {
3751                 /* false label is present */
3752                 if(strcmp(jval,"a") == 0)
3753                         emitSKPNZ;
3754                 else if (strcmp(jval,"c") == 0)
3755                         emitSKPNC;
3756                 else {
3757                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3758                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3759                 }
3760                 
3761                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3762                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3763                 
3764         }
3765         
3766         
3767         /* mark the icode as generated */
3768         ic->generated = 1;
3769 }
3770
3771 #if 0
3772 /*-----------------------------------------------------------------*/
3773 /* genSkip                                                                                                                 */
3774 /*-----------------------------------------------------------------*/
3775 static void genSkip(iCode *ifx,int status_bit)
3776 {
3777         FENTRY;
3778         if(!ifx)
3779                 return;
3780         
3781         if ( IC_TRUE(ifx) ) {
3782                 switch(status_bit) {
3783                 case 'z':
3784                         emitSKPNZ;
3785                         break;
3786                         
3787                 case 'c':
3788                         emitSKPNC;
3789                         break;
3790                         
3791                 case 'd':
3792                         emitSKPDC;
3793                         break;
3794                         
3795                 }
3796                 
3797                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3798                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3799                 
3800         } else {
3801                 
3802                 switch(status_bit) {
3803                         
3804                 case 'z':
3805                         emitSKPZ;
3806                         break;
3807                         
3808                 case 'c':
3809                         emitSKPC;
3810                         break;
3811                         
3812                 case 'd':
3813                         emitSKPDC;
3814                         break;
3815                 }
3816                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3817                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3818                 
3819         }
3820         
3821 }
3822 #endif
3823
3824 /*-----------------------------------------------------------------*/
3825 /* genSkipc                                                                                                        */
3826 /*-----------------------------------------------------------------*/
3827 static void genSkipc(resolvedIfx *rifx)
3828 {
3829         FENTRY;
3830         if(!rifx)
3831                 return;
3832         
3833         if(rifx->condition)
3834                 emitSKPNC;
3835         else
3836                 emitSKPC;
3837         
3838         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3839         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3840         rifx->generated = 1;
3841 }
3842
3843 #if 0
3844 /*-----------------------------------------------------------------*/
3845 /* genSkipz2                                                                                                       */
3846 /*-----------------------------------------------------------------*/
3847 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3848 {
3849         FENTRY;
3850         if(!rifx)
3851                 return;
3852         
3853         if( (rifx->condition ^ invert_condition) & 1)
3854                 emitSKPZ;
3855         else
3856                 emitSKPNZ;
3857         
3858         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3859         rifx->generated = 1;
3860 }
3861 #endif
3862
3863 #if 0
3864 /*-----------------------------------------------------------------*/
3865 /* genSkipz                                                        */
3866 /*-----------------------------------------------------------------*/
3867 static void genSkipz(iCode *ifx, int condition)
3868 {
3869         FENTRY;
3870         assert (ifx != NULL);
3871         
3872         if(condition)
3873                 emitSKPNZ;
3874         else
3875                 emitSKPZ;
3876         
3877         if ( IC_TRUE(ifx) )
3878                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3879         else
3880                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3881         
3882         if ( IC_TRUE(ifx) )
3883                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3884         else
3885                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3886         
3887 }
3888 #endif
3889
3890 #if 0
3891 /*-----------------------------------------------------------------*/
3892 /* genSkipCond                                                     */
3893 /*-----------------------------------------------------------------*/
3894 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3895 {
3896         FENTRY;
3897         if(!rifx)
3898                 return;
3899         
3900         if(rifx->condition)
3901                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3902         else
3903                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3904         
3905         
3906         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3907         rifx->generated = 1;
3908 }
3909 #endif
3910
3911 #if 0
3912 /*-----------------------------------------------------------------*/
3913 /* genChkZeroes :- greater or less than comparison                 */
3914 /*     For each byte in a literal that is zero, inclusive or the   */
3915 /*     the corresponding byte in the operand with W                */
3916 /*     returns true if any of the bytes are zero                   */
3917 /*-----------------------------------------------------------------*/
3918 static int genChkZeroes(operand *op, int lit,  int size)
3919 {
3920         
3921         int i;
3922         int flag =1;
3923         
3924         while(size--) {
3925                 i = (lit >> (size*8)) & 0xff;
3926                 
3927                 if(i==0) {
3928                         if(flag) 
3929                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3930                         else
3931                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3932                         flag = 0;
3933                 }
3934         }
3935         
3936         return (flag==0);
3937 }
3938 #endif
3939
3940
3941 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3942 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3943 #define DEBUGpc           emitpComment
3944
3945 /*-----------------------------------------------------------------*/
3946 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3947 /*                  aop (if it's NOT a literal) or from lit (if    */
3948 /*                  aop is a literal)                              */
3949 /*-----------------------------------------------------------------*/
3950 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3951   if (aop->type == AOP_LIT) {
3952     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3953   } else {
3954     emitpcode (POC_MOVFW, popGet (aop, offset));
3955   }
3956 }
3957
3958 /* genCmp performs a left < right comparison, stores
3959  * the outcome in result (if != NULL) and generates
3960  * control flow code for the ifx (if != NULL).
3961  *
3962  * This version leaves in sequences like
3963  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3964  * which should be optmized by the peephole
3965  * optimizer - RN 2005-01-01 */
3966 static void genCmp (operand *left,operand *right,
3967                     operand *result, iCode *ifx, int sign)
3968 {
3969   resolvedIfx rIfx;
3970   int size;
3971   int offs;
3972   symbol *templbl;
3973   operand *dummy;
3974   unsigned long lit;
3975   unsigned long mask;
3976   int performedLt;
3977   int invert_result = 0;
3978
3979   FENTRY;
3980   
3981   assert (AOP_SIZE(left) == AOP_SIZE(right));
3982   assert (left && right);
3983
3984   size = AOP_SIZE(right) - 1;
3985   mask = (0x100UL << (size*8)) - 1;
3986   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3987   performedLt = 1;
3988   templbl = NULL;
3989   lit = 0;
3990   
3991   resolveIfx (&rIfx, ifx);
3992
3993   /**********************************************************************
3994    * handle bits - bit compares are promoted to int compares seemingly! *
3995    **********************************************************************/
3996 #if 0
3997   // THIS IS COMPLETELY UNTESTED!
3998   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3999     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4000     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4001     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4002
4003     emitSETC;
4004     // 1 < {0,1} is false --> clear C by skipping the next instruction
4005     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4006     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4007     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4008     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4009     emitCLRC; // only skipped for left=0 && right=1
4010
4011     goto correct_result_in_carry;
4012   } // if
4013 #endif
4014
4015   /*************************************************
4016    * make sure that left is register (or the like) *
4017    *************************************************/
4018   if (!isAOP_REGlike(left)) {
4019     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4020     assert (isAOP_LIT(left));
4021     assert (isAOP_REGlike(right));
4022     // swap left and right
4023     // left < right <==> right > left <==> (right >= left + 1)
4024     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4025
4026     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4027       // MAXVALUE < right? always false
4028       if (performedLt) emitCLRC; else emitSETC;
4029       goto correct_result_in_carry;
4030     } // if
4031
4032     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4033     // that's why we handled it above.
4034     lit++;
4035
4036     dummy = left;
4037     left = right;
4038     right = dummy;
4039
4040     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4041   } else if (isAOP_LIT(right)) {
4042     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4043   } // if
4044
4045   assert (isAOP_REGlike(left)); // left must be register or the like
4046   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4047
4048   /*************************************************
4049    * special cases go here                         *
4050    *************************************************/
4051
4052   if (isAOP_LIT(right)) {
4053     if (!sign) {
4054       // unsigned comparison to a literal
4055       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4056       if (lit == 0) {
4057         // unsigned left < 0? always false
4058         if (performedLt) emitCLRC; else emitSETC;
4059         goto correct_result_in_carry;
4060       }
4061     } else {
4062       // signed comparison to a literal
4063       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4064       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4065         // signed left < 0x80000000? always false
4066         if (performedLt) emitCLRC; else emitSETC;
4067         goto correct_result_in_carry;
4068       } else if (lit == 0) {
4069         // compare left < 0; set CARRY if SIGNBIT(left) is set
4070         if (performedLt) emitSETC; else emitCLRC;
4071         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4072         if (performedLt) emitCLRC; else emitSETC;
4073         goto correct_result_in_carry;
4074       }
4075     } // if (!sign)
4076   } // right is literal
4077
4078   /*************************************************
4079    * perform a general case comparison             *
4080    * make sure we get CARRY==1 <==> left >= right  *
4081    *************************************************/
4082   // compare most significant bytes
4083   //DEBUGpc ("comparing bytes at offset %d", size);
4084   if (!sign) {
4085     // unsigned comparison
4086     pic14_mov2w_regOrLit (AOP(right), lit, size);
4087     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4088   } else {
4089     // signed comparison
4090     // (add 2^n to both operands then perform an unsigned comparison)
4091     if (isAOP_LIT(right)) {
4092       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4093       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4094
4095       if (litbyte == 0x80) {
4096         // left >= 0x80 -- always true, but more bytes to come
4097         mov2w (AOP(left), size);
4098         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4099         emitSETC;
4100       } else {
4101         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4102         mov2w (AOP(left), size);
4103         emitpcode (POC_ADDLW, popGetLit (0x80));
4104         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4105       } // if
4106     } else {
4107       pCodeOp *pctemp = popGetTempReg();
4108       mov2w (AOP(left), size);
4109       emitpcode (POC_ADDLW, popGetLit (0x80));
4110       emitpcode (POC_MOVWF, pctemp);
4111       mov2w (AOP(right), size);
4112       emitpcode (POC_ADDLW, popGetLit (0x80));
4113       emitpcode (POC_SUBFW, pctemp);
4114       popReleaseTempReg(pctemp);
4115     }
4116   } // if (!sign)
4117
4118   // compare remaining bytes (treat as unsigned case from above)
4119   templbl = newiTempLabel ( NULL );
4120   offs = size;
4121   while (offs--) {
4122     //DEBUGpc ("comparing bytes at offset %d", offs);
4123     emitSKPZ;
4124     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4125     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4126     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4127   } // while (offs)
4128   emitpLabel (templbl->key);
4129   goto result_in_carry;
4130
4131 result_in_carry:
4132   
4133   /****************************************************
4134    * now CARRY contains the result of the comparison: *
4135    * SUBWF sets CARRY iff                             *
4136    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4137    * (F=left, W=right)                                *
4138    ****************************************************/
4139
4140   if (performedLt) {
4141     invert_result = 1;
4142     // value will be used in the following genSkipc()
4143     rIfx.condition ^= 1;
4144   } // if
4145
4146 correct_result_in_carry:
4147
4148   // assign result to variable (if neccessary)
4149   if (result && AOP_TYPE(result) != AOP_CRY) {
4150     //DEBUGpc ("assign result");
4151     size = AOP_SIZE(result);
4152     while (size--) {
4153       emitpcode (POC_CLRF, popGet (AOP(result), size));
4154     } // while
4155     if (invert_result) {
4156       emitSKPC;
4157       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4158     } else {
4159       emitpcode (POC_RLF, popGet (AOP(result), 0));
4160     }
4161   } // if (result)
4162
4163   // perform conditional jump
4164   if (ifx) {
4165     //DEBUGpc ("generate control flow");
4166     genSkipc (&rIfx);
4167     ifx->generated = 1;
4168   } // if
4169 }
4170
4171
4172 #if 0
4173 /* OLD VERSION -- BUGGY, DO NOT USE */
4174
4175 /*-----------------------------------------------------------------*/
4176 /* genCmp :- greater or less than comparison                       */
4177 /*-----------------------------------------------------------------*/
4178 static void genCmp (operand *left,operand *right,
4179                                         operand *result, iCode *ifx, int sign)
4180 {
4181         int size; //, offset = 0 ;
4182         unsigned long lit = 0L,i = 0;
4183         resolvedIfx rFalseIfx;
4184         //  resolvedIfx rTrueIfx;
4185         symbol *truelbl;
4186
4187         FENTRY;
4188         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4189         /*
4190         if(ifx) {
4191         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4192         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4193         }
4194         */
4195         
4196         resolveIfx(&rFalseIfx,ifx);
4197         truelbl  = newiTempLabel(NULL);
4198         size = max(AOP_SIZE(left),AOP_SIZE(right));
4199         
4200         DEBUGpic14_AopType(__LINE__,left,right,result);
4201         
4202 #define _swapp
4203         
4204         /* if literal is on the right then swap with left */
4205         if ((AOP_TYPE(right) == AOP_LIT)) {
4206                 operand *tmp = right ;
4207                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4208                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4209 #ifdef _swapp
4210                 
4211                 lit = (lit - 1) & mask;
4212                 right = left;
4213                 left = tmp;
4214                 rFalseIfx.condition ^= 1;
4215 #endif
4216                 
4217         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4218                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4219         }
4220         
4221         
4222         //if(IC_TRUE(ifx) == NULL)
4223         /* if left & right are bit variables */
4224         if (AOP_TYPE(left) == AOP_CRY &&
4225                 AOP_TYPE(right) == AOP_CRY ) {
4226                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4227                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4228         } else {
4229         /* subtract right from left if at the
4230         end the carry flag is set then we know that
4231                 left is greater than right */
4232                 
4233                 symbol *lbl  = newiTempLabel(NULL);
4234                 
4235 #ifndef _swapp
4236                 if(AOP_TYPE(right) == AOP_LIT) {
4237                         
4238                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4239                         
4240                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4241                         
4242                         /* special cases */
4243                         
4244                         if(lit == 0) {
4245                                 
4246                                 if(sign != 0) 
4247                                         genSkipCond(&rFalseIfx,left,size-1,7);
4248                                 else 
4249                                         /* no need to compare to 0...*/
4250                                         /* NOTE: this is a de-generate compare that most certainly 
4251                                         *       creates some dead code. */
4252                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4253                                 
4254                                 if(ifx) ifx->generated = 1;
4255                                 return;
4256                                 
4257                         }
4258                         size--;
4259                         
4260                         if(size == 0) {
4261                                 //i = (lit >> (size*8)) & 0xff;
4262                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4263                                 
4264                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4265                                 
4266                                 i = ((0-lit) & 0xff);
4267                                 if(sign) {
4268                                         if( i == 0x81) { 
4269                                         /* lit is 0x7f, all signed chars are less than
4270                                                 * this except for 0x7f itself */
4271                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4272                                                 genSkipz2(&rFalseIfx,0);
4273                                         } else {
4274                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4275                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4276                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4277                                         }
4278                                         
4279                                 } else {
4280                                         if(lit == 1) {
4281                                                 genSkipz2(&rFalseIfx,1);
4282                                         } else {
4283                                                 emitpcode(POC_ADDLW, popGetLit(i));
4284                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4285                                         }
4286                                 }
4287                                 
4288                                 if(ifx) ifx->generated = 1;
4289                                 return;
4290                         }
4291                         
4292                         /* chars are out of the way. now do ints and longs */
4293                         
4294                         
4295                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4296                         
4297                         /* special cases */
4298                         
4299                         if(sign) {
4300                                 
4301                                 if(lit == 0) {
4302                                         genSkipCond(&rFalseIfx,left,size,7);
4303                                         if(ifx) ifx->generated = 1;
4304                                         return;
4305                                 }
4306                                 
4307                                 if(lit <0x100) {
4308                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4309                                         
4310                                         //rFalseIfx.condition ^= 1;
4311                                         //genSkipCond(&rFalseIfx,left,size,7);
4312                                         //rFalseIfx.condition ^= 1;
4313                                         
4314                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4315                                         if(rFalseIfx.condition)
4316                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4317                                         else
4318                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4319                                         
4320                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4321                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4322                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4323                                         
4324                                         while(size > 1)
4325                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4326                                         
4327                                         if(rFalseIfx.condition) {
4328                                                 emitSKPZ;
4329                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4330                                                 
4331                                         } else {
4332                                                 emitSKPNZ;
4333                                         }
4334                                         
4335                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4336                                         emitpLabel(truelbl->key);
4337                                         if(ifx) ifx->generated = 1;
4338                                         return;
4339                                         
4340                                 }
4341                                 
4342                                 if(size == 1) {
4343                                         
4344                                         if( (lit & 0xff) == 0) {
4345                                                 /* lower byte is zero */
4346                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4347                                                 i = ((lit >> 8) & 0xff) ^0x80;
4348                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4349                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4350                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4351                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4352                                                 
4353                                                 
4354                                                 if(ifx) ifx->generated = 1;
4355                                                 return;
4356                                                 
4357                                         }
4358                                 } else {
4359                                         /* Special cases for signed longs */
4360                                         if( (lit & 0xffffff) == 0) {
4361                                                 /* lower byte is zero */
4362                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4363                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4364                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4365                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4366                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4367                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4368                                                 
4369                                                 
4370                                                 if(ifx) ifx->generated = 1;
4371                                                 return;
4372                                                 
4373                                         }
4374                                         
4375                                 }
4376                                 
4377                                 
4378                                 if(lit & (0x80 << (size*8))) {
4379                                         /* lit is negative */
4380                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4381                                         
4382                                         //genSkipCond(&rFalseIfx,left,size,7);
4383                                         
4384                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4385                                         
4386                                         if(rFalseIfx.condition)
4387                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4388                                         else
4389                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4390                                         
4391                                         
4392                                 } else {
4393                                         /* lit is positive */
4394                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4395                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4396                                         if(rFalseIfx.condition)
4397                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4398                                         else
4399                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4400                                         
4401                                 }
4402                                 
4403                                 /* There are no more special cases, so perform a general compare */
4404                                 
4405                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4406                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4407                                 
4408                                 while(size--) {
4409                                         
4410                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4411                                         emitSKPNZ;
4412                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4413                                 }
4414                                 //rFalseIfx.condition ^= 1;
4415                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4416                                 
4417                                 emitpLabel(truelbl->key);
4418                                 
4419                                 if(ifx) ifx->generated = 1;
4420                                 return;
4421                                 
4422                                 
4423                         }
4424
4425
4426                         /* sign is out of the way. So now do an unsigned compare */
4427                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4428
4429
4430                         /* General case - compare to an unsigned literal on the right.*/
4431
4432                         i = (lit >> (size*8)) & 0xff;
4433                         emitpcode(POC_MOVLW, popGetLit(i));
4434                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4435                         while(size--) {
4436                                 i = (lit >> (size*8)) & 0xff;
4437                                 
4438                                 if(i) {
4439                                         emitpcode(POC_MOVLW, popGetLit(i));
4440                                         emitSKPNZ;
4441                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4442                                 } else {
4443                                 /* this byte of the lit is zero, 
4444                                         *if it's not the last then OR in the variable */
4445                                         if(size)
4446                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4447                                 }
4448                         }
4449
4450
4451                 emitpLabel(lbl->key);
4452                 //if(emitFinalCheck)
4453                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4454                 if(sign)
4455                         emitpLabel(truelbl->key);
4456
4457                 if(ifx) ifx->generated = 1;
4458                 return;
4459
4460
4461                 }
4462 #endif  // _swapp
4463
4464                 if(AOP_TYPE(left) == AOP_LIT) {
4465                         //symbol *lbl = newiTempLabel(NULL);
4466                         
4467                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4468                         
4469                         
4470                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4471                         
4472                         /* Special cases */
4473                         if((lit == 0) && (sign == 0)){
4474                                 
4475                                 size--;
4476                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4477                                 while(size) 
4478                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4479                                 
4480                                 genSkipz2(&rFalseIfx,0);
4481                                 if(ifx) ifx->generated = 1;
4482                                 return;
4483                         }
4484                         
4485                         if(size==1) {
4486                                 /* Special cases */
4487                                 lit &= 0xff;
4488                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4489                                         /* degenerate compare can never be true */
4490                                         if(rFalseIfx.condition == 0)
4491                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4492                                         
4493                                         if(ifx) ifx->generated = 1;
4494                                         return;
4495                                 }
4496                                 
4497                                 if(sign) {
4498                                         /* signed comparisons to a literal byte */
4499                                         
4500                                         int lp1 = (lit+1) & 0xff;
4501                                         
4502                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4503                                         switch (lp1) {
4504                                         case 0:
4505                                                 rFalseIfx.condition ^= 1;
4506                                                 genSkipCond(&rFalseIfx,right,0,7);
4507                                                 break;
4508                                         case 0x7f:
4509                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4510                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4511                                                 genSkipz2(&rFalseIfx,1);
4512                                                 break;
4513                                         default:
4514                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4515                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4516                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4517                                                 rFalseIfx.condition ^= 1;
4518                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4519                                                 break;
4520                                         }
4521                                         if(ifx) ifx->generated = 1;
4522                                 } else {
4523                                         /* unsigned comparisons to a literal byte */
4524                                         
4525                                         switch(lit & 0xff ) {
4526                                         case 0:
4527                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4528                                                 genSkipz2(&rFalseIfx,0);
4529                                                 if(ifx) ifx->generated = 1;
4530                                                 break;
4531                                         case 0x7f:
4532                                                 genSkipCond(&rFalseIfx,right,0,7);
4533                                                 if(ifx) ifx->generated = 1;
4534                                                 break;
4535                                                 
4536                                         default:
4537                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4538                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4539                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4540                                                 rFalseIfx.condition ^= 1;
4541                                                 if (AOP_TYPE(result) == AOP_CRY) {
4542                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4543                                                         if(ifx) ifx->generated = 1;
4544                                                 } else {
4545                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4546                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4547                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4548                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4549                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4550                                                 }       
4551                                                 break;
4552                                         }
4553                                 }
4554                                 
4555                                 //goto check_carry;
4556                                 return;
4557                                 
4558                         } else {
4559                                 
4560                                 /* Size is greater than 1 */
4561                                 
4562                                 if(sign) {
4563                                         int lp1 = lit+1;
4564                                         
4565                                         size--;
4566                                         
4567                                         if(lp1 == 0) {
4568                                                 /* this means lit = 0xffffffff, or -1 */
4569                                                 
4570                                                 
4571                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4572                                                 rFalseIfx.condition ^= 1;
4573                                                 genSkipCond(&rFalseIfx,right,size,7);
4574                                                 if(ifx) ifx->generated = 1;
4575                                                 return;
4576                                         }
4577                                         
4578                                         if(lit == 0) {
4579                                                 int s = size;
4580                                                 
4581                                                 if(rFalseIfx.condition) {
4582                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4583                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4584                                                 }
4585                                                 
4586                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4587                                                 while(size--)
4588                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4589                                                 
4590                                                 
4591                                                 emitSKPZ;
4592                                                 if(rFalseIfx.condition) {
4593                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4594                                                         emitpLabel(truelbl->key);
4595                                                 }else {
4596                                                         rFalseIfx.condition ^= 1;
4597                                                         genSkipCond(&rFalseIfx,right,s,7);
4598                                                 }
4599                                                 
4600                                                 if(ifx) ifx->generated = 1;
4601                                                 return;
4602                                         }
4603                                         
4604                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4605                                                 /* lower byte of signed word is zero */
4606                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4607                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4608                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4609                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4610                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4611                                                 rFalseIfx.condition ^= 1;
4612                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4613                                                 
4614                                                 
4615                                                 if(ifx) ifx->generated = 1;
4616                                                 return;
4617                                         }
4618                                         
4619                                         if(lit & (0x80 << (size*8))) {
4620                                                 /* Lit is less than zero */
4621                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4622                                                 //rFalseIfx.condition ^= 1;
4623                                                 //genSkipCond(&rFalseIfx,left,size,7);
4624                                                 //rFalseIfx.condition ^= 1;
4625                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4626                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4627                                                 
4628                                                 if(rFalseIfx.condition)
4629                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4630                                                 else
4631                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4632                                                 
4633                                                 
4634                                         } else {
4635                                                 /* Lit is greater than or equal to zero */
4636                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4637                                                 //rFalseIfx.condition ^= 1;
4638                                                 //genSkipCond(&rFalseIfx,right,size,7);
4639                                                 //rFalseIfx.condition ^= 1;
4640                                                 
4641                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4642                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4643                                                 
4644                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4645                                                 if(rFalseIfx.condition)
4646                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4647                                                 else
4648                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4649                                                 
4650                                         }
4651                                         
4652                                         
4653                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4654                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4655                                         
4656                                         while(size--) {
4657                                                 
4658                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4659                                                 emitSKPNZ;
4660                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4661                                         }
4662                                         rFalseIfx.condition ^= 1;
4663                                         //rFalseIfx.condition = 1;
4664                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4665                                         
4666                                         emitpLabel(truelbl->key);
4667                                         
4668                                         if(ifx) ifx->generated = 1;
4669                                         return;
4670                                         // end of if (sign)
4671                                 } else {
4672                                         
4673                                         /* compare word or long to an unsigned literal on the right.*/
4674                                         
4675                                         
4676                                         size--;
4677                                         if(lit < 0xff) {
4678                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4679                                                 switch (lit) {
4680                                                 case 0:
4681                                                         break; /* handled above */
4682                                                 /*
4683                                                 case 0xff:
4684                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4685                                                         while(size--)
4686                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4687                                                         genSkipz2(&rFalseIfx,0);
4688                                                         break;
4689                                                 */
4690                                                 default:
4691                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4692                                                         while(--size)
4693                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4694                                                         
4695                                                         emitSKPZ;
4696                                                         if(rFalseIfx.condition)
4697                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4698                                                         else
4699                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4700                                                         
4701                                                         
4702                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4703                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4704                                                         
4705                                                         rFalseIfx.condition ^= 1;
4706                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4707                                                 }
4708                                                 
4709                                                 emitpLabel(truelbl->key);
4710                                                 
4711                                                 if(ifx) ifx->generated = 1;
4712                                                 return;
4713                                         }
4714                                         
4715                                         
4716                                         lit++;
4717                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4718                                         i = (lit >> (size*8)) & 0xff;
4719                                         
4720                                         emitpcode(POC_MOVLW, popGetLit(i));
4721                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4722                                         
4723                                         while(size--) {
4724                                                 i = (lit >> (size*8)) & 0xff;
4725                                                 
4726                                                 if(i) {
4727                                                         emitpcode(POC_MOVLW, popGetLit(i));
4728                                                         emitSKPNZ;
4729                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4730                                                 } else {
4731                                                 /* this byte of the lit is zero, 
4732                                                         *if it's not the last then OR in the variable */
4733                                                         if(size)
4734                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4735                                                 }
4736                                         }
4737                                         
4738                                         
4739                                         emitpLabel(lbl->key);
4740                                         
4741                                         rFalseIfx.condition ^= 1;
4742                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4743                                 }
4744                                 
4745                                 if(sign)
4746                                         emitpLabel(truelbl->key);
4747                                 if(ifx) ifx->generated = 1;
4748                                 return;
4749                         }
4750                 }
4751                 /* Compare two variables */
4752                 
4753                 DEBUGpic14_emitcode(";sign","%d",sign);
4754                 
4755                 size--;
4756                 if(sign) {
4757                         /* Sigh. thus sucks... */
4758                         if(size) {
4759                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4760                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4761                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4762                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4763                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4764                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4765                         } else {
4766                                 /* Signed char comparison */
4767                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4768                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4769                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4770                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4771                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4772                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4773                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4774                                 
4775                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4776                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4777                                 
4778                                 if(ifx) ifx->generated = 1;
4779                                 return;
4780                         }
4781                         
4782                 } else {
4783                         
4784                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4785                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4786                 }
4787                 
4788                 
4789                 /* The rest of the bytes of a multi-byte compare */
4790                 while (size) {
4791                         
4792                         emitSKPZ;
4793                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4794                         size--;
4795                         
4796                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4797                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4798                         
4799                         
4800                 }
4801                 
4802                 emitpLabel(lbl->key);
4803                 
4804                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4805                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4806                         (AOP_TYPE(result) == AOP_REG)) {
4807                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4808                         emitpcode(POC_RLF, popGet(AOP(result),0));
4809                 } else {
4810                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4811                 }       
4812                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4813                 if(ifx) ifx->generated = 1;
4814                 
4815                 return;
4816                 
4817         }
4818         
4819         // check_carry:
4820         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4821                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4822                 pic14_outBitC(result);
4823         } else {
4824                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4825                 /* if the result is used in the next
4826                 ifx conditional branch then generate
4827                 code a little differently */
4828                 if (ifx )
4829                         genIfxJump (ifx,"c");
4830                 else
4831                         pic14_outBitC(result);
4832                 /* leave the result in acc */
4833         }
4834         
4835 }
4836 #endif
4837
4838 /*-----------------------------------------------------------------*/
4839 /* genCmpGt :- greater than comparison                             */
4840 /*-----------------------------------------------------------------*/
4841 static void genCmpGt (iCode *ic, iCode *ifx)
4842 {
4843         operand *left, *right, *result;
4844         sym_link *letype , *retype;
4845         int sign ;
4846         
4847         FENTRY;
4848         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4849         left = IC_LEFT(ic);
4850         right= IC_RIGHT(ic);
4851         result = IC_RESULT(ic);
4852         
4853         letype = getSpec(operandType(left));
4854         retype =getSpec(operandType(right));
4855         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4856         /* assign the amsops */
4857         aopOp (left,ic,FALSE);
4858         aopOp (right,ic,FALSE);
4859         aopOp (result,ic,TRUE);
4860         
4861         genCmp(right, left, result, ifx, sign);
4862         
4863         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4864         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4865         freeAsmop(result,NULL,ic,TRUE); 
4866 }
4867
4868 /*-----------------------------------------------------------------*/
4869 /* genCmpLt - less than comparisons                                */
4870 /*-----------------------------------------------------------------*/
4871 static void genCmpLt (iCode *ic, iCode *ifx)
4872 {
4873         operand *left, *right, *result;
4874         sym_link *letype , *retype;
4875         int sign ;
4876         
4877         FENTRY;
4878         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4879         left = IC_LEFT(ic);
4880         right= IC_RIGHT(ic);
4881         result = IC_RESULT(ic);
4882         
4883         letype = getSpec(operandType(left));
4884         retype =getSpec(operandType(right));
4885         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4886         
4887         /* assign the amsops */
4888         aopOp (left,ic,FALSE);
4889         aopOp (right,ic,FALSE);
4890         aopOp (result,ic,TRUE);
4891         
4892         genCmp(left, right, result, ifx, sign);
4893         
4894         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4895         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4896         freeAsmop(result,NULL,ic,TRUE); 
4897 }
4898
4899 #if 0
4900 /*-----------------------------------------------------------------*/
4901 /* genc16bit2lit - compare a 16 bit value to a literal             */
4902 /*-----------------------------------------------------------------*/
4903 static void genc16bit2lit(operand *op, int lit, int offset)
4904 {
4905         int i;
4906         
4907         FENTRY;
4908         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4909         if( (lit&0xff) == 0) 
4910                 i=1;
4911         else
4912                 i=0;
4913         
4914         switch( BYTEofLONG(lit,i)) { 
4915         case 0:
4916                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4917                 break;
4918         case 1:
4919                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4920                 break;
4921         case 0xff:
4922                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4923                 break;
4924         default:
4925                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4926                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4927         }
4928         
4929         i ^= 1;
4930         
4931         switch( BYTEofLONG(lit,i)) { 
4932         case 0:
4933                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4934                 break;
4935         case 1:
4936                 emitSKPNZ;
4937                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4938                 break;
4939         case 0xff:
4940                 emitSKPNZ;
4941                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4942                 break;
4943         default:
4944                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4945                 emitSKPNZ;
4946                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4947                 
4948         }
4949         
4950 }
4951 #endif
4952
4953 #if 0
4954 /*-----------------------------------------------------------------*/
4955 /* gencjneshort - compare and jump if not equal                    */
4956 /*-----------------------------------------------------------------*/
4957 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4958 {
4959         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4960         int offset = 0;
4961         //resolvedIfx rIfx;
4962         symbol *lbl;
4963         
4964         //unsigned long lit = 0L;
4965         FENTRY;
4966         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4967           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4968           return;
4969         }
4970         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4971         DEBUGpic14_AopType(__LINE__,left,right,result);
4972         
4973         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4974         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4975         if (AOP_SIZE(result)) {
4976           for (offset = 0; offset < AOP_SIZE(result); offset++)
4977             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4978         }
4979         
4980         assert (AOP_SIZE(left) == AOP_SIZE(right));
4981         //resolveIfx(&rIfx,ifx);
4982         lbl = newiTempLabel (NULL);
4983         while (size--)
4984         {
4985           mov2w (AOP(right),size);
4986           emitpcode (POC_XORFW, popGet (AOP(left), size));
4987           if (size)
4988           {
4989             emitSKPZ;
4990             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4991           }
4992         } // while
4993         emitpLabel (lbl->key);
4994         if (AOP_SIZE(result)) {
4995           emitSKPNZ;
4996           emitpcode (POC_INCF, popGet (AOP(result), 0));
4997         } else {
4998           assert (ifx);
4999           genSkipz (ifx, NULL != IC_TRUE(ifx));
5000           ifx->generated = 1;
5001         }
5002         return;
5003 #if 0   
5004         if(result)
5005         {
5006                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5007                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
5008                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
5009                 for (offset=0; offset < AOP_SIZE(result); offset++)
5010                 {
5011                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
5012                 } // for offset
5013         }
5014         
5015         
5016         /* if the left side is a literal or 
5017         if the right is in a pointer register and left 
5018         is not */
5019         if ((AOP_TYPE(left) == AOP_LIT) || 
5020                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5021                 operand *t = right;
5022                 right = left;
5023                 left = t;
5024         }
5025         if(AOP_TYPE(right) == AOP_LIT)
5026                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5027         
5028         /* if the right side is a literal then anything goes */
5029         if (AOP_TYPE(right) == AOP_LIT &&
5030                 AOP_TYPE(left) != AOP_DIR ) {
5031                 switch(size) {
5032                 case 2:
5033                         genc16bit2lit(left, lit, 0);
5034                         emitSKPNZ;
5035                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5036                         break;
5037                 default:
5038                         offset = 0;
5039                         while (size--) {
5040                                 if(lit & 0xff) {
5041                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5042                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5043                                 } else {
5044                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5045                                 }
5046                                 
5047                                 emitSKPNZ;
5048                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5049                                 offset++;
5050                                 lit >>= 8;
5051                         }
5052                         break;
5053                 }
5054         }
5055         
5056         /* if the right side is in a register or in direct space or
5057         if the left is a pointer register & right is not */    
5058         else if (AOP_TYPE(right) == AOP_REG ||
5059                 AOP_TYPE(right) == AOP_DIR || 
5060                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5061                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5062                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5063                 int lbl_key = lbl->key;
5064                 
5065                 if(!result) {
5066                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5067                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5068                                 __FUNCTION__,__LINE__);
5069                         return;
5070                 }
5071                 
5072                 /*     switch(size) { */
5073                 /*     case 2: */
5074                 /*       genc16bit2lit(left, lit, 0); */
5075                 /*       emitSKPNZ; */
5076                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5077                 /*       break; */
5078                 /*     default: */
5079                 offset = 0;
5080                 while (size--) {
5081                         int emit_skip=1;
5082                         if((AOP_TYPE(left) == AOP_DIR) && 
5083                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5084                                 
5085                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5086                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5087                                 
5088                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5089                                 
5090                                 switch (lit & 0xff) {
5091                                 case 0:
5092                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5093                                         break;
5094                                 case 1:
5095                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5096                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5097                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5098                                         emit_skip=0;
5099                                         break;
5100                                 case 0xff:
5101                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5102                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5103                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5104                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5105                                         emit_skip=0;
5106                                         break;
5107                                 default:
5108                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5109                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5110                                 }
5111                                 lit >>= 8;
5112                                 
5113                         } else {
5114                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5115                         }
5116                         if(emit_skip) {
5117                                 if(AOP_TYPE(result) == AOP_CRY) {
5118                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5119                                         if(rIfx.condition)
5120                                                 emitSKPNZ;
5121                                         else
5122                                                 emitSKPZ;
5123                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5124                                 } else {
5125                                         /* fix me. probably need to check result size too */
5126                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5127                                         if(rIfx.condition)
5128                                                 emitSKPZ;
5129                                         else
5130                                                 emitSKPNZ;
5131                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5132                                 }
5133                                 if(ifx)
5134                                         ifx->generated=1;
5135                         }
5136                         emit_skip++;
5137                         offset++;
5138                 }
5139                 /*       break; */
5140                 /*     } */
5141         } else if(AOP_TYPE(right) == AOP_REG &&
5142                 AOP_TYPE(left) != AOP_DIR){
5143
5144                 offset = 0;
5145                 while(size--) {
5146                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5147                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5148                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5149                         if(rIfx.condition)
5150                                 emitSKPNZ;
5151                         else
5152                                 emitSKPZ;
5153                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5154                         offset++;
5155                 }
5156                 
5157         }else{
5158                 /* right is a pointer reg need both a & b */
5159                 offset = 0;
5160                 while(size--) {
5161                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5162                         if(strcmp(l,"b"))
5163                                 pic14_emitcode("mov","b,%s",l);
5164                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5165                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5166                         offset++;
5167                 }
5168         }
5169         
5170         emitpcode(POC_INCF,popGet(AOP(result),0));
5171         if(!rIfx.condition)
5172                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5173         
5174         emitpLabel(lbl->key);
5175         
5176         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5177         
5178         if(ifx)
5179                 ifx->generated = 1;
5180 #endif
5181 }
5182 #endif
5183
5184 #if 0
5185 /*-----------------------------------------------------------------*/
5186 /* gencjne - compare and jump if not equal                         */
5187 /*-----------------------------------------------------------------*/
5188 static void gencjne(operand *left, operand *right, iCode *ifx)
5189 {
5190         symbol *tlbl  = newiTempLabel(NULL);
5191         
5192         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5193         gencjneshort(left, right, lbl);
5194         
5195         pic14_emitcode("mov","a,%s",one);
5196         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5197         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5198         pic14_emitcode("clr","a");
5199         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5200         
5201         emitpLabel(lbl->key);
5202         emitpLabel(tlbl->key);
5203         
5204 }
5205 #endif
5206
5207 /*-----------------------------------------------------------------*/
5208 /* genCmpEq - generates code for equal to                          */
5209 /*-----------------------------------------------------------------*/
5210 static void genCmpEq (iCode *ic, iCode *ifx)
5211 {
5212   operand *left, *right, *result;
5213   int size;
5214   symbol *false_label;
5215
5216   FENTRY;
5217   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5218
5219   if(ifx)
5220     DEBUGpic14_emitcode ("; ifx is non-null","");
5221   else
5222     DEBUGpic14_emitcode ("; ifx is null","");
5223
5224   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5225   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5226   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5227
5228   DEBUGpic14_AopType(__LINE__,left,right,result);
5229
5230   /* if literal, move literal to right */ 
5231   if (op_isLitLike (IC_LEFT(ic))) {
5232     operand *tmp = right ;
5233     right = left;
5234     left = tmp;
5235   }
5236
5237   false_label = NULL;
5238   if (ifx && !IC_TRUE(ifx))
5239   {
5240     assert (IC_FALSE(ifx));
5241     false_label = IC_FALSE(ifx);
5242   }
5243
5244   size = min(AOP_SIZE(left),AOP_SIZE(right));
5245   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5246   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5247
5248   /* assume left != right */
5249   {
5250     int i;
5251     for (i=0; i < AOP_SIZE(result); i++)
5252     {
5253       emitpcode(POC_CLRF, popGet(AOP(result),i));
5254     }
5255   }
5256
5257   if (AOP_TYPE(right) == AOP_LIT)
5258   {
5259     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5260     int i;
5261     size = AOP_SIZE(left);
5262     assert(!op_isLitLike(left));
5263
5264     switch (lit)
5265     {
5266       case 0:
5267         mov2w(AOP(left), 0);
5268         for (i=1; i < size; i++)
5269           emitpcode(POC_IORFW,popGet(AOP(left),i));
5270         /* now Z is set iff `left == right' */
5271         emitSKPZ;
5272         if (!false_label) false_label = newiTempLabel(NULL);
5273         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5274         break;
5275
5276       default:
5277         for (i=0; i < size; i++)
5278         {
5279           mov2w(AOP(left),i);
5280           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5281           /* now Z is cleared if `left != right' */
5282           emitSKPZ;
5283           if (!false_label) false_label = newiTempLabel(NULL);
5284           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5285         } // for i
5286         break;
5287     } // switch (lit)
5288   }
5289   else
5290   {
5291     /* right is no literal */
5292     int i;
5293
5294     for (i=0; i < size; i++)
5295     {
5296       mov2w(AOP(right),i);
5297       emitpcode(POC_XORFW,popGet(AOP(left),i));
5298       /* now Z is cleared if `left != right' */
5299       emitSKPZ;
5300       if (!false_label) false_label = newiTempLabel(NULL);
5301       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5302     } // for i
5303   }
5304
5305   /* if we reach here, left == right */
5306
5307   if (AOP_SIZE(result) > 0)
5308   {
5309     emitpcode(POC_INCF, popGet(AOP(result),0));
5310   }
5311
5312   if (ifx && IC_TRUE(ifx))
5313   {
5314     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5315   }
5316
5317   if (false_label && (!ifx || IC_TRUE(ifx)))
5318     emitpLabel(false_label->key);
5319
5320   if (ifx) ifx->generated = 1;
5321
5322   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5323   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5324   freeAsmop(result,NULL,ic,TRUE);
5325 }
5326
5327 /*-----------------------------------------------------------------*/
5328 /* ifxForOp - returns the icode containing the ifx for operand     */
5329 /*-----------------------------------------------------------------*/
5330 static iCode *ifxForOp ( operand *op, iCode *ic )
5331 {
5332         FENTRY;
5333         /* if true symbol then needs to be assigned */
5334         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5335         if (IS_TRUE_SYMOP(op))
5336                 return NULL ;
5337         
5338         /* if this has register type condition and
5339         the next instruction is ifx with the same operand
5340         and live to of the operand is upto the ifx only then */
5341         if (ic->next &&
5342                 ic->next->op == IFX &&
5343                 IC_COND(ic->next)->key == op->key &&
5344                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5345                 return ic->next;
5346         
5347         if (ic->next &&
5348                 ic->next->op == IFX &&
5349                 IC_COND(ic->next)->key == op->key) {
5350                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5351                 return ic->next;
5352         }
5353         
5354         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5355         if (ic->next &&
5356                 ic->next->op == IFX)
5357                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5358         
5359         if (ic->next &&
5360                 ic->next->op == IFX &&
5361                 IC_COND(ic->next)->key == op->key) {
5362                 DEBUGpic14_emitcode ("; "," key is okay");
5363                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5364                         OP_SYMBOL(op)->liveTo,
5365                         ic->next->seq);
5366         }
5367         
5368         
5369         return NULL;
5370 }
5371 /*-----------------------------------------------------------------*/
5372 /* genAndOp - for && operation                                     */
5373 /*-----------------------------------------------------------------*/
5374 static void genAndOp (iCode *ic)
5375 {
5376         operand *left,*right, *result;
5377         /*     symbol *tlbl; */
5378         
5379         FENTRY;
5380         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5381         /* note here that && operations that are in an
5382         if statement are taken away by backPatchLabels
5383         only those used in arthmetic operations remain */
5384         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5385         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5386         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5387         
5388         DEBUGpic14_AopType(__LINE__,left,right,result);
5389         
5390         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5391         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5392         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5393         
5394         /* if both are bit variables */
5395         /*     if (AOP_TYPE(left) == AOP_CRY && */
5396         /*         AOP_TYPE(right) == AOP_CRY ) { */
5397         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5398         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5399         /*         pic14_outBitC(result); */
5400         /*     } else { */
5401         /*         tlbl = newiTempLabel(NULL); */
5402         /*         pic14_toBoolean(left);     */
5403         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5404         /*         pic14_toBoolean(right); */
5405         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5406         /*         pic14_outBitAcc(result); */
5407         /*     } */
5408         
5409         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5410         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5411         freeAsmop(result,NULL,ic,TRUE);
5412 }
5413
5414
5415 /*-----------------------------------------------------------------*/
5416 /* genOrOp - for || operation                                      */
5417 /*-----------------------------------------------------------------*/
5418 /*
5419 tsd pic port -
5420 modified this code, but it doesn't appear to ever get called
5421 */
5422
5423 static void genOrOp (iCode *ic)
5424 {
5425         operand *left,*right, *result;
5426         symbol *tlbl;
5427         int i;
5428         
5429         /* note here that || operations that are in an
5430         if statement are taken away by backPatchLabels
5431         only those used in arthmetic operations remain */
5432         FENTRY;
5433         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5434         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5435         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5436         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5437         
5438         DEBUGpic14_AopType(__LINE__,left,right,result);
5439
5440         for (i=0; i < AOP_SIZE(result); i++)
5441         {
5442                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5443         } // for i
5444
5445         tlbl = newiTempLabel(NULL);
5446         pic14_toBoolean(left);
5447         emitSKPZ;
5448         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5449         pic14_toBoolean(right);
5450         emitpLabel(tlbl->key);
5451         /* here Z is clear IFF `left || right' */
5452         emitSKPZ;
5453         emitpcode(POC_INCF, popGet(AOP(result), 0));
5454         
5455         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5456         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5457         freeAsmop(result,NULL,ic,TRUE);            
5458 }
5459
5460 /*-----------------------------------------------------------------*/
5461 /* isLiteralBit - test if lit == 2^n                               */
5462 /*-----------------------------------------------------------------*/
5463 static int isLiteralBit(unsigned long lit)
5464 {
5465         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5466                 0x100L,0x200L,0x400L,0x800L,
5467                 0x1000L,0x2000L,0x4000L,0x8000L,
5468                 0x10000L,0x20000L,0x40000L,0x80000L,
5469                 0x100000L,0x200000L,0x400000L,0x800000L,
5470                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5471                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5472         int idx;
5473         
5474         FENTRY;
5475         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5476         for(idx = 0; idx < 32; idx++)
5477                 if(lit == pw[idx])
5478                         return idx+1;
5479                 return 0;
5480 }
5481
5482 /*-----------------------------------------------------------------*/
5483 /* continueIfTrue -                                                */
5484 /*-----------------------------------------------------------------*/
5485 static void continueIfTrue (iCode *ic)
5486 {
5487         FENTRY;
5488         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5489         if(IC_TRUE(ic))
5490                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5491         ic->generated = 1;
5492 }
5493
5494 /*-----------------------------------------------------------------*/
5495 /* jmpIfTrue -                                                     */
5496 /*-----------------------------------------------------------------*/
5497 static void jumpIfTrue (iCode *ic)
5498 {
5499         FENTRY;
5500         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5501         if(!IC_TRUE(ic))
5502                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5503         ic->generated = 1;
5504 }
5505
5506 /*-----------------------------------------------------------------*/
5507 /* jmpTrueOrFalse -                                                */
5508 /*-----------------------------------------------------------------*/
5509 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5510 {
5511         FENTRY;
5512         // ugly but optimized by peephole
5513         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5514         if(IC_TRUE(ic)){
5515                 symbol *nlbl = newiTempLabel(NULL);
5516                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5517                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5518                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5519                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5520         }
5521         else{
5522                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5523                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5524         }
5525         ic->generated = 1;
5526 }
5527
5528 /*-----------------------------------------------------------------*/
5529 /* genAnd  - code for and                                          */
5530 /*-----------------------------------------------------------------*/
5531 static void genAnd (iCode *ic, iCode *ifx)
5532 {
5533         operand *left, *right, *result;
5534         int size, offset=0;  
5535         unsigned long lit = 0L;
5536         int bytelit = 0;
5537         resolvedIfx rIfx;
5538         
5539         FENTRY;
5540         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5541         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5542         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5543         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5544         
5545         resolveIfx(&rIfx,ifx);
5546         
5547         /* if left is a literal & right is not then exchange them */
5548         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5549                 AOP_NEEDSACC(left)) {
5550                 operand *tmp = right ;
5551                 right = left;
5552                 left = tmp;
5553         }
5554         
5555         /* if result = right then exchange them */
5556         if(pic14_sameRegs(AOP(result),AOP(right))){
5557                 operand *tmp = right ;
5558                 right = left;
5559                 left = tmp;
5560         }
5561         
5562         /* if right is bit then exchange them */
5563         if (AOP_TYPE(right) == AOP_CRY &&
5564                 AOP_TYPE(left) != AOP_CRY){
5565                 operand *tmp = right ;
5566                 right = left;
5567                 left = tmp;
5568         }
5569         if(AOP_TYPE(right) == AOP_LIT)
5570                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5571         
5572         size = AOP_SIZE(result);
5573         
5574         DEBUGpic14_AopType(__LINE__,left,right,result);
5575         
5576         // if(bit & yy)
5577         // result = bit & yy;
5578         if (AOP_TYPE(left) == AOP_CRY){
5579                 // c = bit & literal;
5580                 if(AOP_TYPE(right) == AOP_LIT){
5581                         if(lit & 1) {
5582                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5583                                         // no change
5584                                         goto release;
5585                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5586                         } else {
5587                                 // bit(result) = 0;
5588                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5589                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5590                                         goto release;
5591                                 }
5592                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5593                                         jumpIfTrue(ifx);
5594                                         goto release;
5595                                 }
5596                                 pic14_emitcode("clr","c");
5597                         }
5598                 } else {
5599                         if (AOP_TYPE(right) == AOP_CRY){
5600                                 // c = bit & bit;
5601                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5602                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5603                         } else {
5604                                 // c = bit & val;
5605                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5606                                 // c = lsb
5607                                 pic14_emitcode("rrc","a");
5608                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5609                         }
5610                 }
5611                 // bit = c
5612                 // val = c
5613                 if(size)
5614                         pic14_outBitC(result);
5615                 // if(bit & ...)
5616                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5617                         genIfxJump(ifx, "c");           
5618                 goto release ;
5619         }
5620         
5621         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5622         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5623         if((AOP_TYPE(right) == AOP_LIT) &&
5624                 (AOP_TYPE(result) == AOP_CRY) &&
5625                 (AOP_TYPE(left) != AOP_CRY)){
5626                 int posbit = isLiteralBit(lit);
5627                 /* left &  2^n */
5628                 if(posbit){
5629                         posbit--;
5630                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5631                         // bit = left & 2^n
5632                         if(size)
5633                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5634                         // if(left &  2^n)
5635                         else{
5636                                 if(ifx){
5637                                         int offset = 0;
5638                                         while (posbit > 7) {
5639                                                 posbit -= 8;
5640                                                 offset++;
5641                                         }
5642                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5643                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5644                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5645                                         
5646                                         ifx->generated = 1;
5647                                 }
5648                                 goto release;
5649                         }
5650                 } else {
5651                         symbol *tlbl = newiTempLabel(NULL);
5652                         int sizel = AOP_SIZE(left);
5653                         if(size)
5654                                 pic14_emitcode("setb","c");
5655                         while(sizel--){
5656                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5657                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5658                                         // byte ==  2^n ?
5659                                         if((posbit = isLiteralBit(bytelit)) != 0)
5660                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5661                                         else{
5662                                                 if(bytelit != 0x0FFL)
5663                                                         pic14_emitcode("anl","a,%s",
5664                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5665                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5666                                         }
5667                                 }
5668                                 offset++;
5669                         }
5670                         // bit = left & literal
5671                         if(size){
5672                                 pic14_emitcode("clr","c");
5673                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5674                         }
5675                         // if(left & literal)
5676                         else{
5677                                 if(ifx)
5678                                         jmpTrueOrFalse(ifx, tlbl);
5679                                 goto release ;
5680                         }
5681                 }
5682                 pic14_outBitC(result);
5683                 goto release ;
5684         }
5685         
5686         /* if left is same as result */
5687         if(pic14_sameRegs(AOP(result),AOP(left))){
5688                 int know_W = -1;
5689                 for(;size--; offset++,lit>>=8) {
5690                         if(AOP_TYPE(right) == AOP_LIT){
5691                                 switch(lit & 0xff) {
5692                                 case 0x00:
5693                                         /*  and'ing with 0 has clears the result */
5694                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5695                                         break;
5696                                 case 0xff:
5697                                         /* and'ing with 0xff is a nop when the result and left are the same */
5698                                         break;
5699                                         
5700                                 default:
5701                                         {
5702                                                 int p = my_powof2( (~lit) & 0xff );
5703                                                 if(p>=0) {
5704                                                         /* only one bit is set in the literal, so use a bcf instruction */
5705                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5706                                                         
5707                                                 } else {
5708                                                         if(know_W != (int)(lit&0xff))
5709                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5710                                                         know_W = lit &0xff;
5711                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5712                                                 }
5713                                         }    
5714                                 }
5715                         } else {
5716                                 if (AOP_TYPE(left) == AOP_ACC) {
5717                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5718                                 } else {        
5719                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5720                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5721                                         
5722                                 }
5723                         }
5724                 }
5725                 
5726         } else {
5727                 // left & result in different registers
5728                 if(AOP_TYPE(result) == AOP_CRY){
5729                         // result = bit
5730                         // if(size), result in bit
5731                         // if(!size && ifx), conditional oper: if(left & right)
5732                         symbol *tlbl = newiTempLabel(NULL);
5733                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5734                         if(size)
5735                                 pic14_emitcode("setb","c");
5736                         while(sizer--){
5737                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5738                                 pic14_emitcode("anl","a,%s",
5739                                         aopGet(AOP(left),offset,FALSE,FALSE));
5740                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5741                                 offset++;
5742                         }
5743                         if(size){
5744                                 CLRC;
5745                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5746                                 pic14_outBitC(result);
5747                         } else if(ifx)
5748                                 jmpTrueOrFalse(ifx, tlbl);
5749                 } else {
5750                         for(;(size--);offset++) {
5751                                 // normal case
5752                                 // result = left & right
5753                                 if(AOP_TYPE(right) == AOP_LIT){
5754                                         int t = (lit >> (offset*8)) & 0x0FFL;
5755                                         switch(t) { 
5756                                         case 0x00:
5757                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5758                                                 break;
5759                                         case 0xff:
5760                                                 if(AOP_TYPE(left) != AOP_ACC) {
5761                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5762                                                 }
5763                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5764                                                 break;
5765                                         default:
5766                                                 if(AOP_TYPE(left) == AOP_ACC) {
5767                                                         emitpcode(POC_ANDLW, popGetLit(t));
5768                                                 } else {
5769                                                         emitpcode(POC_MOVLW, popGetLit(t));
5770                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5771                                                 }
5772                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5773                                         }
5774                                         continue;
5775                                 }
5776                                 
5777                                 if (AOP_TYPE(left) == AOP_ACC) {
5778                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5779                                 } else {
5780                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5781                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5782                                 }
5783                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5784                         }
5785                 }
5786         }
5787         
5788 release :
5789         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5790         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5791         freeAsmop(result,NULL,ic,TRUE);     
5792 }
5793
5794 /*-----------------------------------------------------------------*/
5795 /* genOr  - code for or                                            */
5796 /*-----------------------------------------------------------------*/
5797 static void genOr (iCode *ic, iCode *ifx)
5798 {
5799         operand *left, *right, *result;
5800         int size, offset=0;
5801         unsigned long lit = 0L;
5802         
5803         FENTRY;
5804         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5805         
5806         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5807         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5808         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5809         
5810         DEBUGpic14_AopType(__LINE__,left,right,result);
5811         
5812         /* if left is a literal & right is not then exchange them */
5813         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5814                 AOP_NEEDSACC(left)) {
5815                 operand *tmp = right ;
5816                 right = left;
5817                 left = tmp;
5818         }
5819         
5820         /* if result = right then exchange them */
5821         if(pic14_sameRegs(AOP(result),AOP(right))){
5822                 operand *tmp = right ;
5823                 right = left;
5824                 left = tmp;
5825         }
5826         
5827         /* if right is bit then exchange them */
5828         if (AOP_TYPE(right) == AOP_CRY &&
5829                 AOP_TYPE(left) != AOP_CRY){
5830                 operand *tmp = right ;
5831                 right = left;
5832                 left = tmp;
5833         }
5834         
5835         DEBUGpic14_AopType(__LINE__,left,right,result);
5836         
5837         if(AOP_TYPE(right) == AOP_LIT)
5838                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5839         
5840         size = AOP_SIZE(result);
5841         
5842         // if(bit | yy)
5843         // xx = bit | yy;
5844         if (AOP_TYPE(left) == AOP_CRY){
5845                 if(AOP_TYPE(right) == AOP_LIT){
5846                         // c = bit & literal;
5847                         if(lit){
5848                                 // lit != 0 => result = 1
5849                                 if(AOP_TYPE(result) == AOP_CRY){
5850                                         if(size)
5851                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5852                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5853                                         //   AOP(result)->aopu.aop_dir,
5854                                         //   AOP(result)->aopu.aop_dir);
5855                                         else if(ifx)
5856                                                 continueIfTrue(ifx);
5857                                         goto release;
5858                                 }
5859                         } else {
5860                                 // lit == 0 => result = left
5861                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5862                                         goto release;
5863                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5864                         }
5865                 } else {
5866                         if (AOP_TYPE(right) == AOP_CRY){
5867                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5868                                         // c = bit | bit;
5869                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5870                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5871                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5872                                         
5873                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5874                                                 AOP(result)->aopu.aop_dir,
5875                                                 AOP(result)->aopu.aop_dir);
5876                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5877                                                 AOP(right)->aopu.aop_dir,
5878                                                 AOP(right)->aopu.aop_dir);
5879                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5880                                                 AOP(result)->aopu.aop_dir,
5881                                                 AOP(result)->aopu.aop_dir);
5882                                 } else {
5883                                         if( AOP_TYPE(result) == AOP_ACC) {
5884                                                 emitpcode(POC_MOVLW, popGetLit(0));
5885                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5886                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5887                                                 emitpcode(POC_MOVLW, popGetLit(1));
5888                                                 
5889                                         } else {
5890                                                 
5891                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5892                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5893                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5894                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5895                                                 
5896                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5897                                                         AOP(result)->aopu.aop_dir,
5898                                                         AOP(result)->aopu.aop_dir);
5899                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5900                                                         AOP(right)->aopu.aop_dir,
5901                                                         AOP(right)->aopu.aop_dir);
5902                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5903                                                         AOP(left)->aopu.aop_dir,
5904                                                         AOP(left)->aopu.aop_dir);
5905                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5906                                                         AOP(result)->aopu.aop_dir,
5907                                                         AOP(result)->aopu.aop_dir);
5908                                         }
5909                                 }
5910                         } else {
5911                                 // c = bit | val;
5912                                 symbol *tlbl = newiTempLabel(NULL);
5913                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5914                                 
5915                                 
5916                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5917                                 if( AOP_TYPE(right) == AOP_ACC) {
5918                                         emitpcode(POC_IORLW, popGetLit(0));
5919                                         emitSKPNZ;
5920                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5921                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5922                                 }
5923                                 
5924                                 
5925                                 
5926                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5927                                         pic14_emitcode(";XXX setb","c");
5928                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5929                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5930                                 pic14_toBoolean(right);
5931                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5932                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5933                                         jmpTrueOrFalse(ifx, tlbl);
5934                                         goto release;
5935                                 } else {
5936                                         CLRC;
5937                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5938                                 }
5939                         }
5940                 }
5941                 // bit = c
5942                 // val = c
5943                 if(size)
5944                         pic14_outBitC(result);
5945                 // if(bit | ...)
5946                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5947                         genIfxJump(ifx, "c");           
5948                 goto release ;
5949         }
5950
5951         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5952         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5953         if((AOP_TYPE(right) == AOP_LIT) &&
5954           (AOP_TYPE(result) == AOP_CRY) &&
5955           (AOP_TYPE(left) != AOP_CRY)){
5956                 if(lit){
5957                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5958                         // result = 1
5959                         if(size)
5960                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5961                         else 
5962                                 continueIfTrue(ifx);
5963                         goto release;
5964                 } else {
5965                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5966                         // lit = 0, result = boolean(left)
5967                         if(size)
5968                                 pic14_emitcode(";XXX setb","c");
5969                         pic14_toBoolean(right);
5970                         if(size){
5971                                 symbol *tlbl = newiTempLabel(NULL);
5972                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5973                                 CLRC;
5974                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5975                         } else {
5976                                 genIfxJump (ifx,"a");
5977                                 goto release;
5978                         }
5979                 }
5980                 pic14_outBitC(result);
5981                 goto release ;
5982         }
5983
5984         /* if left is same as result */
5985         if(pic14_sameRegs(AOP(result),AOP(left))){
5986                 int know_W = -1;
5987                 for(;size--; offset++,lit>>=8) {
5988                         if(AOP_TYPE(right) == AOP_LIT){
5989                                 if((lit & 0xff) == 0)
5990                                         /*  or'ing with 0 has no effect */
5991                                         continue;
5992                                 else {
5993                                         int p = my_powof2(lit & 0xff);
5994                                         if(p>=0) {
5995                                                 /* only one bit is set in the literal, so use a bsf instruction */
5996                                                 emitpcode(POC_BSF,
5997                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5998                                         } else {
5999                                                 if(know_W != (int)(lit & 0xff))
6000                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
6001                                                 know_W = lit & 0xff;
6002                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
6003                                         }
6004                                         
6005                                 }
6006                         } else {
6007                                 if (AOP_TYPE(left) == AOP_ACC) {
6008                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
6009                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6010                                 } else {        
6011                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
6012                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
6013                                         
6014                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
6015                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
6016                                         
6017                                 }
6018                         }
6019                 }
6020         } else {
6021                 // left & result in different registers
6022                 if(AOP_TYPE(result) == AOP_CRY){
6023                         // result = bit
6024                         // if(size), result in bit
6025                         // if(!size && ifx), conditional oper: if(left | right)
6026                         symbol *tlbl = newiTempLabel(NULL);
6027                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6028                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6029                         
6030                         
6031                         if(size)
6032                                 pic14_emitcode(";XXX setb","c");
6033                         while(sizer--){
6034                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6035                                 pic14_emitcode(";XXX orl","a,%s",
6036                                         aopGet(AOP(left),offset,FALSE,FALSE));
6037                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6038                                 offset++;
6039                         }
6040                         if(size){
6041                                 CLRC;
6042                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6043                                 pic14_outBitC(result);
6044                         } else if(ifx)
6045                                 jmpTrueOrFalse(ifx, tlbl);
6046                 } else for(;(size--);offset++){
6047                         // normal case
6048                         // result = left | right
6049                         if(AOP_TYPE(right) == AOP_LIT){
6050                                 int t = (lit >> (offset*8)) & 0x0FFL;
6051                                 switch(t) { 
6052                                 case 0x00:
6053                                         if (AOP_TYPE(left) != AOP_ACC) {
6054                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6055                                         }
6056                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6057                                         
6058                                         break;
6059                                 default:
6060                                         if (AOP_TYPE(left) == AOP_ACC) {
6061                                                 emitpcode(POC_IORLW,  popGetLit(t));
6062                                         } else {
6063                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6064                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6065                                         }
6066                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6067                                 }
6068                                 continue;
6069                         }
6070                         
6071                         // faster than result <- left, anl result,right
6072                         // and better if result is SFR
6073                         if (AOP_TYPE(left) == AOP_ACC) {
6074                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6075                         } else {
6076                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6077                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6078                         }
6079                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6080                 }
6081         }
6082
6083 release :
6084         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6085         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6086         freeAsmop(result,NULL,ic,TRUE);     
6087 }
6088
6089 /*-----------------------------------------------------------------*/
6090 /* genXor - code for xclusive or                                   */
6091 /*-----------------------------------------------------------------*/
6092 static void genXor (iCode *ic, iCode *ifx)
6093 {
6094         operand *left, *right, *result;
6095         int size, offset=0;
6096         unsigned long lit = 0L;
6097         
6098         FENTRY;
6099         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6100         
6101         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6102         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6103         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6104         
6105         /* if left is a literal & right is not ||
6106         if left needs acc & right does not */
6107         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6108                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6109                 operand *tmp = right ;
6110                 right = left;
6111                 left = tmp;
6112         }
6113         
6114         /* if result = right then exchange them */
6115         if(pic14_sameRegs(AOP(result),AOP(right))){
6116                 operand *tmp = right ;
6117                 right = left;
6118                 left = tmp;
6119         }
6120         
6121         /* if right is bit then exchange them */
6122         if (AOP_TYPE(right) == AOP_CRY &&
6123                 AOP_TYPE(left) != AOP_CRY){
6124                 operand *tmp = right ;
6125                 right = left;
6126                 left = tmp;
6127         }
6128         if(AOP_TYPE(right) == AOP_LIT)
6129                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6130         
6131         size = AOP_SIZE(result);
6132         
6133         // if(bit ^ yy)
6134         // xx = bit ^ yy;
6135         if (AOP_TYPE(left) == AOP_CRY){
6136                 if(AOP_TYPE(right) == AOP_LIT){
6137                         // c = bit & literal;
6138                         if(lit>>1){
6139                                 // lit>>1  != 0 => result = 1
6140                                 if(AOP_TYPE(result) == AOP_CRY){
6141                                         if(size)
6142                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6143                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6144                                         else if(ifx)
6145                                                 continueIfTrue(ifx);
6146                                         goto release;
6147                                 }
6148                                 pic14_emitcode("setb","c");
6149                         } else{
6150                                 // lit == (0 or 1)
6151                                 if(lit == 0){
6152                                         // lit == 0, result = left
6153                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6154                                                 goto release;
6155                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6156                                 } else{
6157                                         // lit == 1, result = not(left)
6158                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6159                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6160                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6161                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6162                                                 goto release;
6163                                         } else {
6164                                                 assert ( !"incomplete genXor" );
6165                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6166                                                 pic14_emitcode("cpl","c");
6167                                         }
6168                                 }
6169                         }
6170                         
6171                 } else {
6172                         // right != literal
6173                         symbol *tlbl = newiTempLabel(NULL);
6174                         if (AOP_TYPE(right) == AOP_CRY){
6175                                 // c = bit ^ bit;
6176                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6177                         }
6178                         else{
6179                                 int sizer = AOP_SIZE(right);
6180                                 // c = bit ^ val
6181                                 // if val>>1 != 0, result = 1
6182                                 pic14_emitcode("setb","c");
6183                                 while(sizer){
6184                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6185                                         if(sizer == 1)
6186                                                 // test the msb of the lsb
6187                                                 pic14_emitcode("anl","a,#0xfe");
6188                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6189                                         sizer--;
6190                                 }
6191                                 // val = (0,1)
6192                                 pic14_emitcode("rrc","a");
6193                         }
6194                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6195                         pic14_emitcode("cpl","c");
6196                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6197                 }
6198                 // bit = c
6199                 // val = c
6200                 if(size)
6201                         pic14_outBitC(result);
6202                 // if(bit | ...)
6203                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6204                         genIfxJump(ifx, "c");           
6205                 goto release ;
6206         }
6207         
6208         if(pic14_sameRegs(AOP(result),AOP(left))){
6209                 /* if left is same as result */
6210                 for(;size--; offset++) {
6211                         if(AOP_TYPE(right) == AOP_LIT){
6212                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6213                                 if(t == 0x00L)
6214                                         continue;
6215                                 else
6216                                         if (IS_AOP_PREG(left)) {
6217                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6218                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6219                                                 aopPut(AOP(result),"a",offset);
6220                                         } else {
6221                                                 emitpcode(POC_MOVLW, popGetLit(t));
6222                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6223                                                 pic14_emitcode("xrl","%s,%s",
6224                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6225                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6226                                         }
6227                         } else {
6228                                 if (AOP_TYPE(left) == AOP_ACC)
6229                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6230                                 else {
6231                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6232                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6233                                         /*
6234                                         if (IS_AOP_PREG(left)) {
6235                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6236                                         aopPut(AOP(result),"a",offset);
6237                                         } else
6238                                         pic14_emitcode("xrl","%s,a",
6239                                         aopGet(AOP(left),offset,FALSE,TRUE));
6240                                         */
6241                                 }
6242                         }
6243                 }
6244         } else {
6245                 // left & result in different registers
6246                 if(AOP_TYPE(result) == AOP_CRY){
6247                         // result = bit
6248                         // if(size), result in bit
6249                         // if(!size && ifx), conditional oper: if(left ^ right)
6250                         symbol *tlbl = newiTempLabel(NULL);
6251                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6252                         if(size)
6253                                 pic14_emitcode("setb","c");
6254                         while(sizer--){
6255                                 if((AOP_TYPE(right) == AOP_LIT) &&
6256                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6257                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6258                                 } else {
6259                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6260                                         pic14_emitcode("xrl","a,%s",
6261                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6262                                 }
6263                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6264                                 offset++;
6265                         }
6266                         if(size){
6267                                 CLRC;
6268                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6269                                 pic14_outBitC(result);
6270                         } else if(ifx)
6271                                 jmpTrueOrFalse(ifx, tlbl);
6272                 } else for(;(size--);offset++){
6273                         // normal case
6274                         // result = left & right
6275                         if(AOP_TYPE(right) == AOP_LIT){
6276                                 int t = (lit >> (offset*8)) & 0x0FFL;
6277                                 switch(t) { 
6278                                 case 0x00:
6279                                         if (AOP_TYPE(left) != AOP_ACC) {
6280                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6281                                         }
6282                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6283                                         pic14_emitcode("movf","%s,w",
6284                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6285                                         pic14_emitcode("movwf","%s",
6286                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6287                                         break;
6288                                 case 0xff:
6289                                         if (AOP_TYPE(left) == AOP_ACC) {
6290                                                 emitpcode(POC_XORLW, popGetLit(t));
6291                                         } else {
6292                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6293                                         }
6294                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6295                                         break;
6296                                 default:
6297                                         if (AOP_TYPE(left) == AOP_ACC) {
6298                                                 emitpcode(POC_XORLW, popGetLit(t));
6299                                         } else {
6300                                                 emitpcode(POC_MOVLW, popGetLit(t));
6301                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6302                                         }
6303                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6304                                         pic14_emitcode("movlw","0x%x",t);
6305                                         pic14_emitcode("xorwf","%s,w",
6306                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6307                                         pic14_emitcode("movwf","%s",
6308                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6309                                         
6310                                 }
6311                                 continue;
6312                         }
6313                         
6314                         // faster than result <- left, anl result,right
6315                         // and better if result is SFR
6316                         if (AOP_TYPE(left) == AOP_ACC) {
6317                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6318                         } else {
6319                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6320                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6321                         }
6322                         if ( AOP_TYPE(result) != AOP_ACC){
6323                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6324                         }
6325                 }
6326         }
6327         
6328 release :
6329         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6331         freeAsmop(result,NULL,ic,TRUE);     
6332 }
6333
6334 /*-----------------------------------------------------------------*/
6335 /* genInline - write the inline code out                           */
6336 /*-----------------------------------------------------------------*/
6337 static void genInline (iCode *ic)
6338 {
6339   char *buffer, *bp, *bp1;
6340
6341   FENTRY;
6342   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6343
6344   _G.inLine += (!options.asmpeep);
6345
6346   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6347   strcpy(buffer,IC_INLINE(ic));
6348
6349   /* emit each line as a code */
6350   while (*bp) {
6351     if (*bp == '\n') {
6352       *bp++ = '\0';
6353       
6354       if(*bp1)
6355         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6356       bp1 = bp;
6357     } else {
6358       if (*bp == ':') {
6359         bp++;
6360         *bp = '\0';
6361         bp++;
6362
6363         /* print label, use this special format with NULL directive
6364          * to denote that the argument should not be indented with tab */
6365         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6366
6367         bp1 = bp;
6368       } else
6369         bp++;
6370     }
6371   }
6372   if ((bp1 != bp) && *bp1)
6373     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6374
6375   Safe_free(buffer);
6376
6377   _G.inLine -= (!options.asmpeep);
6378 }
6379
6380 /*-----------------------------------------------------------------*/
6381 /* genRRC - rotate right with carry                                */
6382 /*-----------------------------------------------------------------*/
6383 static void genRRC (iCode *ic)
6384 {
6385         operand *left , *result ;
6386         int size, offset = 0, same;
6387         
6388         FENTRY;
6389         /* rotate right with carry */
6390         left = IC_LEFT(ic);
6391         result=IC_RESULT(ic);
6392         aopOp (left,ic,FALSE);
6393         aopOp (result,ic,FALSE);
6394         
6395         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6396         
6397         same = pic14_sameRegs(AOP(result),AOP(left));
6398         
6399         size = AOP_SIZE(result);    
6400         
6401         /* get the lsb and put it into the carry */
6402         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6403         
6404         offset = 0 ;
6405         
6406         while(size--) {
6407                 
6408                 if(same) {
6409                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6410                 } else {
6411                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6412                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6413                 }
6414                 
6415                 offset++;
6416         }
6417         
6418         freeAsmop(left,NULL,ic,TRUE);
6419         freeAsmop(result,NULL,ic,TRUE);
6420 }
6421
6422 /*-----------------------------------------------------------------*/
6423 /* genRLC - generate code for rotate left with carry               */
6424 /*-----------------------------------------------------------------*/
6425 static void genRLC (iCode *ic)
6426 {    
6427         operand *left , *result ;
6428         int size, offset = 0;
6429         int same;
6430         
6431         FENTRY;
6432         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6433         /* rotate right with carry */
6434         left = IC_LEFT(ic);
6435         result=IC_RESULT(ic);
6436         aopOp (left,ic,FALSE);
6437         aopOp (result,ic,FALSE);
6438         
6439         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6440         
6441         same = pic14_sameRegs(AOP(result),AOP(left));
6442         
6443         /* move it to the result */
6444         size = AOP_SIZE(result);    
6445         
6446         /* get the msb and put it into the carry */
6447         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6448         
6449         offset = 0 ;
6450         
6451         while(size--) {
6452                 
6453                 if(same) {
6454                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6455                 } else {
6456                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6457                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6458                 }
6459                 
6460                 offset++;
6461         }
6462         
6463         
6464         freeAsmop(left,NULL,ic,TRUE);
6465         freeAsmop(result,NULL,ic,TRUE);
6466 }
6467
6468 /*-----------------------------------------------------------------*/
6469 /* genGetHbit - generates code get highest order bit               */
6470 /*-----------------------------------------------------------------*/
6471 static void genGetHbit (iCode *ic)
6472 {
6473         operand *left, *result;
6474         left = IC_LEFT(ic);
6475         result=IC_RESULT(ic);
6476         aopOp (left,ic,FALSE);
6477         aopOp (result,ic,FALSE);
6478         
6479         FENTRY;
6480         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6481         /* get the highest order byte into a */
6482         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6483         if(AOP_TYPE(result) == AOP_CRY){
6484                 pic14_emitcode("rlc","a");
6485                 pic14_outBitC(result);
6486         }
6487         else{
6488                 pic14_emitcode("rl","a");
6489                 pic14_emitcode("anl","a,#0x01");
6490                 pic14_outAcc(result);
6491         }
6492         
6493         
6494         freeAsmop(left,NULL,ic,TRUE);
6495         freeAsmop(result,NULL,ic,TRUE);
6496 }
6497
6498 /*-----------------------------------------------------------------*/
6499 /* AccLsh - shift left accumulator by known count                  */
6500 /* MARK: pic14 always rotates through CARRY!                       */
6501 /*-----------------------------------------------------------------*/
6502 static void AccLsh (pCodeOp *pcop,int shCount)
6503 {
6504         FENTRY;
6505         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6506         shCount &= 0x0007;              // shCount : 0..7
6507         switch(shCount){
6508         case 0 :
6509                 return;
6510                 break;
6511         case 1 :
6512                 emitCLRC;
6513                 emitpcode(POC_RLF,pcop);
6514                 return;
6515                 break;
6516         case 2 :
6517                 emitpcode(POC_RLF,pcop);
6518                 emitpcode(POC_RLF,pcop);
6519                 break;
6520         case 3 :
6521                 emitpcode(POC_RLF,pcop);
6522                 emitpcode(POC_RLF,pcop);
6523                 emitpcode(POC_RLF,pcop);
6524                 break;
6525         case 4 :
6526                 emitpcode(POC_SWAPF,pcop);
6527                 break;
6528         case 5 :
6529                 emitpcode(POC_SWAPF,pcop);
6530                 emitpcode(POC_RLF,pcop);
6531                 break;
6532         case 6 :
6533                 emitpcode(POC_SWAPF,pcop);
6534                 emitpcode(POC_RLF,pcop);
6535                 emitpcode(POC_RLF,pcop);
6536                 break;
6537         case 7 :
6538                 emitpcode(POC_RRFW,pcop);
6539                 emitpcode(POC_RRF,pcop);
6540                 break;
6541         }
6542         /* clear invalid bits */
6543         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6544         emitpcode(POC_ANDWF, pcop);
6545 }
6546
6547 /*-----------------------------------------------------------------*/
6548 /* AccRsh - shift right accumulator by known count                 */
6549 /* MARK: pic14 always rotates through CARRY!                       */
6550 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6551 /*            1: mask out invalid bits (zero-extend)               */
6552 /*            2: sign-extend result (pretty slow)                  */
6553 /*-----------------------------------------------------------------*/
6554 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6555 {
6556         FENTRY;
6557         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6558         shCount &= 0x0007;              // shCount : 0..7
6559         switch(shCount){
6560         case 0 :
6561                 return;
6562                 break;
6563         case 1 :
6564                 /* load sign if needed */
6565                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6566                 else if (mask_mode == 1) emitCLRC;
6567                 emitpcode(POC_RRF,pcop);
6568                 return;
6569                 break;
6570         case 2 :
6571                 /* load sign if needed */
6572                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6573                 emitpcode(POC_RRF,pcop);
6574                 /* load sign if needed */
6575                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6576                 emitpcode(POC_RRF,pcop);
6577                 if (mask_mode == 2) return;
6578                 break;
6579         case 3 :
6580                 /* load sign if needed */
6581                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6582                 emitpcode(POC_RRF,pcop);
6583                 /* load sign if needed */
6584                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6585                 emitpcode(POC_RRF,pcop);
6586                 /* load sign if needed */
6587                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6588                 emitpcode(POC_RRF,pcop);
6589                 if (mask_mode == 2) return;
6590                 break;
6591         case 4 :
6592                 emitpcode(POC_SWAPF,pcop);
6593                 break;
6594         case 5 :
6595                 emitpcode(POC_SWAPF,pcop);
6596                 emitpcode(POC_RRF,pcop);
6597                 break;
6598         case 6 :
6599                 emitpcode(POC_SWAPF,pcop);
6600                 emitpcode(POC_RRF,pcop);
6601                 emitpcode(POC_RRF,pcop);
6602                 break;
6603         case 7 :
6604                 if (mask_mode == 2)
6605                 {
6606                         /* load sign */
6607                         emitpcode(POC_RLFW,pcop);
6608                         emitpcode(POC_CLRF,pcop);
6609                         emitSKPNC;
6610                         emitpcode(POC_COMF,pcop);
6611                         return;
6612                 } else {
6613                         emitpcode(POC_RLFW,pcop);
6614                         emitpcode(POC_RLF,pcop);
6615                 }
6616                 break;
6617         }
6618
6619         if (mask_mode == 0)
6620         {
6621                 /* leave invalid bits undefined */
6622                 return;
6623         }
6624         
6625         /* clear invalid bits -- zero-extend */
6626         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6627         emitpcode(POC_ANDWF, pcop);
6628
6629         if (mask_mode == 2) {
6630           /* sign-extend */
6631           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6632           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6633           emitpcode(POC_IORWF, pcop);
6634         }
6635 }
6636
6637 #if 0
6638 /*-----------------------------------------------------------------*/
6639 /* AccSRsh - signed right shift accumulator by known count                 */
6640 /*-----------------------------------------------------------------*/
6641 static void AccSRsh (int shCount)
6642 {
6643         symbol *tlbl ;
6644         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6645         if(shCount != 0){
6646                 if(shCount == 1){
6647                         pic14_emitcode("mov","c,acc.7");
6648                         pic14_emitcode("rrc","a");
6649                 } else if(shCount == 2){
6650                         pic14_emitcode("mov","c,acc.7");
6651                         pic14_emitcode("rrc","a");
6652                         pic14_emitcode("mov","c,acc.7");
6653                         pic14_emitcode("rrc","a");
6654                 } else {
6655                         tlbl = newiTempLabel(NULL);
6656                         /* rotate right accumulator */
6657                         AccRol(8 - shCount);
6658                         /* and kill the higher order bits */
6659                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6660                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6661                         pic14_emitcode("orl","a,#0x%02x",
6662                                 (unsigned char)~SRMask[shCount]);
6663                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6664                 }
6665         }
6666 }
6667
6668 /*-----------------------------------------------------------------*/
6669 /* shiftR1Left2Result - shift right one byte from left to result   */
6670 /*-----------------------------------------------------------------*/
6671 static void shiftR1Left2ResultSigned (operand *left, int offl,
6672                                                                           operand *result, int offr,
6673                                                                           int shCount)
6674 {
6675         int same;
6676         
6677         FENTRY;
6678         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6679         
6680         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6681         
6682         switch(shCount) {
6683         case 1:
6684                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6685                 if(same) 
6686                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6687                 else {
6688                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6689                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6690                 }
6691                 
6692                 break;
6693         case 2:
6694                 
6695                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6696                 if(same) 
6697                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6698                 else {
6699                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6700                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6701                 }
6702                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6703                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6704                 
6705                 break;
6706                 
6707         case 3:
6708                 if(same)
6709                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6710                 else {
6711                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6712                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6713                 }
6714                 
6715                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6716                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6717                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6718                 
6719                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6720                 emitpcode(POC_IORLW, popGetLit(0xe0));
6721                 
6722                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6723                 break;
6724                 
6725         case 4:
6726                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6727                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6728                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6729                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6730                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6731                 break;
6732         case 5:
6733                 if(same) {
6734                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6735                 } else {
6736                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6737                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6738                 }
6739                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6740                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6741                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6742                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6743                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6744                 break;
6745                 
6746         case 6:
6747                 if(same) {
6748                         emitpcode(POC_MOVLW, popGetLit(0x00));
6749                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6750                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6751                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6752                         emitpcode(POC_IORLW, popGetLit(0x01));
6753                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6754                 } else {
6755                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6756                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6757                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6758                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6759                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6760                 }
6761                 break;
6762                 
6763         case 7:
6764                 if(same) {
6765                         emitpcode(POC_MOVLW, popGetLit(0x00));
6766                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6767                         emitpcode(POC_MOVLW, popGetLit(0xff));
6768                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6769                 } else {
6770                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6771                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6772                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6773                 }
6774                 
6775         default:
6776                 break;
6777         }
6778 }
6779
6780 /*-----------------------------------------------------------------*/
6781 /* shiftR1Left2Result - shift right one byte from left to result   */
6782 /*-----------------------------------------------------------------*/
6783 static void shiftR1Left2Result (operand *left, int offl,
6784                                                                 operand *result, int offr,
6785                                                                 int shCount, int sign)
6786 {
6787         int same;
6788         
6789         FENTRY;
6790         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6791         
6792         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6793         
6794         /* Copy the msb into the carry if signed. */
6795         if(sign) {
6796                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6797                 return;
6798         }
6799         
6800         
6801         
6802         switch(shCount) {
6803         case 1:
6804                 emitCLRC;
6805                 if(same) 
6806                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6807                 else {
6808                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6809                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6810                 }
6811                 break;
6812         case 2:
6813                 emitCLRC;
6814                 if(same) {
6815                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6816                 } else {
6817                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6818                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6819                 }
6820                 emitCLRC;
6821                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6822                 
6823                 break;
6824         case 3:
6825                 if(same)
6826                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6827                 else {
6828                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6829                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6830                 }
6831                 
6832                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6833                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6834                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6835                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6836                 break;
6837                 
6838         case 4:
6839                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6840                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6841                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6842                 break;
6843                 
6844         case 5:
6845                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6846                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6847                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6848                 emitCLRC;
6849                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6850                 
6851                 break;
6852         case 6:
6853                 
6854                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6855                 emitpcode(POC_ANDLW, popGetLit(0x80));
6856                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6857                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6858                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6859                 break;
6860                 
6861         case 7:
6862                 
6863                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6864                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6865                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6866                 
6867                 break;
6868                 
6869         default:
6870                 break;
6871         }
6872 }
6873
6874 /*-----------------------------------------------------------------*/
6875 /* shiftL1Left2Result - shift left one byte from left to result    */
6876 /*-----------------------------------------------------------------*/
6877 static void shiftL1Left2Result (operand *left, int offl,
6878                                                                 operand *result, int offr, int shCount)
6879 {
6880         int same;
6881         
6882         //    char *l;
6883         FENTRY;
6884         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6885         
6886         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6887         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6888         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6889         //    MOVA(l);
6890         /* shift left accumulator */
6891         //AccLsh(shCount); // don't comment out just yet...
6892         //    aopPut(AOP(result),"a",offr);
6893         
6894         switch(shCount) {
6895         case 1:
6896                 /* Shift left 1 bit position */
6897                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6898                 if(same) {
6899                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6900                 } else {
6901                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6902                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6903                 }
6904                 break;
6905         case 2:
6906                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6907                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6908                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6909                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6910                 break;
6911         case 3:
6912                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6913                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6914                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6915                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6916                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6917                 break;
6918         case 4:
6919                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6920                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6921                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6922                 break;
6923         case 5:
6924                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6925                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6926                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6927                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6928                 break;
6929         case 6:
6930                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6931                 emitpcode(POC_ANDLW, popGetLit(0x30));
6932                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6933                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6934                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6935                 break;
6936         case 7:
6937                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6938                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6939                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6940                 break;
6941                 
6942         default:
6943                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6944         }
6945         
6946 }
6947 #endif
6948
6949 /*-----------------------------------------------------------------*/
6950 /* movLeft2Result - move byte from left to result                  */
6951 /*-----------------------------------------------------------------*/
6952 static void movLeft2Result (operand *left, int offl,
6953                                                         operand *result, int offr)
6954 {
6955         char *l;
6956         FENTRY;
6957         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6958         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6959                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6960                 
6961                 if (*l == '@' && (IS_AOP_PREG(result))) {
6962                         pic14_emitcode("mov","a,%s",l);
6963                         aopPut(AOP(result),"a",offr);
6964                 } else {
6965                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6966                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6967                 }
6968         }
6969 }
6970
6971 /*-----------------------------------------------------------------*/
6972 /* shiftLeft_Left2ResultLit - shift left by known count            */
6973 /*-----------------------------------------------------------------*/
6974
6975 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6976 {
6977         int size, same, offr, i;
6978
6979         size = AOP_SIZE(left);
6980         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6981         
6982         same = pic14_sameRegs (AOP(left), AOP(result));
6983         
6984         offr = shCount / 8;
6985         shCount = shCount & 0x07;
6986
6987         size -= offr;
6988
6989         switch (shCount)
6990         {
6991         case 0: /* takes 0 or 2N cycles (for offr==0) */
6992                 if (!same || offr) {
6993                         for (i=size-1; i >= 0; i--)
6994                                 movLeft2Result (left, i, result, offr + i);
6995                 } // if
6996                 break;
6997                 
6998         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6999                 if (same && offr) {
7000                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
7001                         shiftLeft_Left2ResultLit (result, result, shCount);
7002                         return; /* prevent clearing result again */
7003                 } else {
7004                         emitCLRC;
7005                         for (i=0; i < size; i++) {
7006                                 if (same && !offr) {
7007                                         emitpcode (POC_RLF, popGet (AOP(left), i));
7008                                 } else {
7009                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
7010                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7011                                 } // if
7012                         } // for
7013                 } // if (offr)
7014                 break;
7015                 
7016         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
7017                 /* works in-place/with offr as well */
7018                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
7019                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7020                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7021
7022                 for (i = size - 2; i >= 0; i--)
7023                 {
7024                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7025                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7026                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7027                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7028                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7029                 } // for i
7030                 break;
7031                 
7032         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7033                 /* works in-place/with offr as well */
7034                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7035                 for (i = size-2; i >= 0; i--) {
7036                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7037                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7038                 } // for i
7039                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7040                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7041                 break;
7042         
7043         default:
7044                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7045                 shiftLeft_Left2ResultLit (result, result, 1);
7046                 return; /* prevent clearing result again */
7047                 break;
7048         } // switch
7049
7050         while (0 < offr--)
7051         {
7052                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7053         } // while
7054 }
7055
7056 /*-----------------------------------------------------------------*/
7057 /* shiftRight_Left2ResultLit - shift right by known count          */
7058 /*-----------------------------------------------------------------*/
7059
7060 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7061 {
7062         int size, same, offr, i;
7063
7064         size = AOP_SIZE(left);
7065         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7066         
7067         same = pic14_sameRegs (AOP(left), AOP(result));
7068         
7069         offr = shCount / 8;
7070         shCount = shCount & 0x07;
7071
7072         size -= offr;
7073
7074         if (size)
7075         {
7076                 switch (shCount)
7077                 {
7078                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7079                         if (!same || offr) {
7080                                 for (i=0; i < size; i++)
7081                                         movLeft2Result (left, i + offr, result, i);
7082                         } // if
7083                         break;
7084                         
7085                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7086                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7087                         if (same && offr) {
7088                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7089                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7090                                 return; /* prevent sign-extending result again */
7091                         } else {
7092                                 emitCLRC;
7093                                 if (sign) {
7094                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7095                                         emitSETC;
7096                                 }
7097                                 for (i = size-1; i >= 0; i--) {
7098                                         if (same && !offr) {
7099                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7100                                         } else {
7101                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7102                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7103                                         }
7104                                 } // for i
7105                         } // if (offr)
7106                         break;
7107                         
7108                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7109                         /* works in-place/with offr as well */
7110                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7111                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7112                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7113
7114                         for (i = 1; i < size; i++)
7115                         {
7116                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7117                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7118                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7119                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7120                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7121                         } // for i
7122
7123                         if (sign)
7124                         {
7125                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7126                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7127                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7128                         } // if
7129                         break;
7130                         
7131                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7132                         /* works in-place/with offr as well */
7133                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7134                         for (i = 0; i < size-1; i++) {
7135                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7136                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7137                         } // for i
7138                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7139                         if (!sign) {
7140                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7141                         } else {
7142                                 emitSKPNC;
7143                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7144                         }
7145                         break;
7146                 
7147                 default:
7148                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7149                         shiftRight_Left2ResultLit (result, result, 1, sign);
7150                         return; /* prevent sign extending result again */
7151                         break;
7152                 } // switch
7153         } // if
7154
7155         addSign (result, size, sign);
7156 }
7157
7158 #if 0
7159 /*-----------------------------------------------------------------*/
7160 /* shiftL2Left2Result - shift left two bytes from left to result   */
7161 /*-----------------------------------------------------------------*/
7162 static void shiftL2Left2Result (operand *left, int offl,
7163                                                                 operand *result, int offr, int shCount)
7164 {
7165         FENTRY;
7166         
7167         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7168         
7169         if(pic14_sameRegs(AOP(result), AOP(left))) {
7170                 switch(shCount) {
7171                 case 0:
7172                         break;
7173                 case 1:
7174                 case 2:
7175                 case 3:
7176                         
7177                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7178                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7179                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7180                         
7181                         while(--shCount) {
7182                                 emitCLRC;
7183                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7184                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7185                         }
7186                         
7187                         break;
7188                 case 4:
7189                 case 5:
7190                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7191                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7192                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7193                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7194                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7195                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7196                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7197                         if(shCount >=5) {
7198                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7199                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7200                         }
7201                         break;
7202                 case 6:
7203                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7204                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7205                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7206                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7207                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7208                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7209                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7210                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7211                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7212                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7213                         break;
7214                 case 7:
7215                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7216                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7217                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7218                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7219                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7220                 }
7221                 
7222         } else {
7223                 switch(shCount) {
7224                 case 0:
7225                         break;
7226                 case 1:
7227                 case 2:
7228                 case 3:
7229                 /* note, use a mov/add for the shift since the mov has a
7230                         chance of getting optimized out */
7231                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7232                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7233                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7234                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7235                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7236                         
7237                         while(--shCount) {
7238                                 emitCLRC;
7239                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7240                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7241                         }
7242                         break;
7243                         
7244                 case 4:
7245                 case 5:
7246                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7247                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7248                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7249                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7250                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7251                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7252                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7253                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7254                         
7255                         
7256                         if(shCount == 5) {
7257                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7258                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7259                         }
7260                         break;
7261                 case 6:
7262                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7263                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7264                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7265                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7266                         
7267                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7268                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7269                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7270                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7271                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7272                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7273                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7274                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7275                         break;
7276                 case 7:
7277                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7278                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7279                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7280                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7281                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7282                 }
7283         }
7284         
7285 }
7286
7287 /*-----------------------------------------------------------------*/
7288 /* shiftR2Left2Result - shift right two bytes from left to result  */
7289 /*-----------------------------------------------------------------*/
7290 static void shiftR2Left2Result (operand *left, int offl,
7291                                                                 operand *result, int offr,
7292                                                                 int shCount, int sign)
7293 {
7294         int same=0;
7295         
7296         FENTRY;
7297         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7298         same = pic14_sameRegs(AOP(result), AOP(left));
7299         
7300         if(same && ((offl + MSB16) == offr)){
7301                 same=1;
7302                 /* don't crash result[offr] */
7303                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7304                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7305         }
7306         /* else {
7307         movLeft2Result(left,offl, result, offr);
7308         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7309         }
7310         */
7311         /* a:x >> shCount (x = lsb(result))*/
7312         /*
7313         if(sign)
7314         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7315         else {
7316         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7317         */
7318         switch(shCount) {
7319         case 0:
7320                 break;
7321         case 1:
7322         case 2:
7323         case 3:
7324                 if(sign)
7325                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7326                 else
7327                         emitCLRC;
7328                 
7329                 if(same) {
7330                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7331                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7332                 } else {
7333                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7334                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7335                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7336                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7337                 }
7338                 
7339                 while(--shCount) {
7340                         if(sign)
7341                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7342                         else
7343                                 emitCLRC;
7344                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7345                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7346                 }
7347                 break;
7348         case 4:
7349         case 5:
7350                 if(same) {
7351                         
7352                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7353                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7354                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7355                         
7356                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7357                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7358                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7359                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7360                 } else {
7361                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7362                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7363                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7364                         
7365                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7366                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7367                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7368                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7369                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7370                 }
7371                 
7372                 if(shCount >=5) {
7373                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7374                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7375                 }
7376                 
7377                 if(sign) {
7378                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7379                         emitpcode(POC_BTFSC, 
7380                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7381                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7382                 }
7383                 
7384                 break;
7385                 
7386         case 6:
7387                 if(same) {
7388                         
7389                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7390                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7391                         
7392                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7393                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7394                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7395                         emitpcode(POC_ANDLW,popGetLit(0x03));
7396                         if(sign) {
7397                                 emitpcode(POC_BTFSC, 
7398                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7399                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7400                         }
7401                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7402                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7403                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7404                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7405                 } else {
7406                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7407                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7408                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7409                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7410                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7411                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7412                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7413                         emitpcode(POC_ANDLW,popGetLit(0x03));
7414                         if(sign) {
7415                                 emitpcode(POC_BTFSC, 
7416                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7417                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7418                         }
7419                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7420                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7421                         
7422                         
7423                 }
7424                 
7425                 break;
7426         case 7:
7427                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7428                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7429                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7430                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7431                 if(sign) {
7432                         emitSKPNC;
7433                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7434                 } else 
7435                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7436   }
7437 }
7438
7439 /*-----------------------------------------------------------------*/
7440 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7441 /*-----------------------------------------------------------------*/
7442 static void shiftLLeftOrResult (operand *left, int offl,
7443                                                                 operand *result, int offr, int shCount)
7444 {
7445         FENTRY;
7446         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7447         
7448         /* shift left accumulator */
7449         AccLsh(left,offl,shCount);
7450         /* or with result */
7451         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7452         assert ( !"broken (modifies left, fails for left==result))" );
7453 }
7454
7455 /*-----------------------------------------------------------------*/
7456 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7457 /*-----------------------------------------------------------------*/
7458 static void shiftRLeftOrResult (operand *left, int offl,
7459                                                                 operand *result, int offr, int shCount)
7460 {
7461         FENTRY;
7462         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7463         
7464         /* shift right accumulator */
7465         AccRsh(left,offl,shCount);
7466         /* or with result */
7467         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7468         assert ( !"broken (modifies left, fails for left==result))" );
7469 }
7470
7471 /*-----------------------------------------------------------------*/
7472 /* genlshOne - left shift a one byte quantity by known count       */
7473 /*-----------------------------------------------------------------*/
7474 static void genlshOne (operand *result, operand *left, int shCount)
7475 {       
7476         FENTRY;
7477         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7478         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7479 }
7480
7481 /*-----------------------------------------------------------------*/
7482 /* genlshTwo - left shift two bytes by known amount != 0           */
7483 /*-----------------------------------------------------------------*/
7484 static void genlshTwo (operand *result,operand *left, int shCount)
7485 {
7486         int size;
7487         
7488         FENTRY;
7489         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7490         size = pic14_getDataSize(result);
7491         
7492         /* if shCount >= 8 */
7493         if (shCount >= 8) {
7494                 shCount -= 8 ;
7495                 
7496                 if (size > 1){
7497                         if (shCount)
7498                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7499                         else 
7500                                 movLeft2Result(left, LSB, result, MSB16);
7501                 }
7502                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7503         }
7504         
7505         /*  1 <= shCount <= 7 */
7506         else {  
7507                 if(size == 1)
7508                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7509                 else 
7510                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7511         }
7512 }
7513
7514 /*-----------------------------------------------------------------*/
7515 /* shiftLLong - shift left one long from left to result            */
7516 /* offl = LSB or MSB16                                             */
7517 /*-----------------------------------------------------------------*/
7518 static void shiftLLong (operand *left, operand *result, int offr )
7519 {
7520         char *l;
7521         int size = AOP_SIZE(result);
7522         
7523         FENTRY;
7524         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7525         if(size >= LSB+offr){
7526                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7527                 MOVA(l);
7528                 pic14_emitcode("add","a,acc");
7529                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7530                         size >= MSB16+offr && offr != LSB )
7531                         pic14_emitcode("xch","a,%s",
7532                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7533                 else      
7534                         aopPut(AOP(result),"a",LSB+offr);
7535         }
7536         
7537         if(size >= MSB16+offr){
7538                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7539                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7540                         MOVA(l);
7541                 }
7542                 pic14_emitcode("rlc","a");
7543                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7544                         size >= MSB24+offr && offr != LSB)
7545                         pic14_emitcode("xch","a,%s",
7546                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7547                 else      
7548                         aopPut(AOP(result),"a",MSB16+offr);
7549         }
7550         
7551         if(size >= MSB24+offr){
7552                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7553                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7554                         MOVA(l);
7555                 }
7556                 pic14_emitcode("rlc","a");
7557                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7558                         size >= MSB32+offr && offr != LSB )
7559                         pic14_emitcode("xch","a,%s",
7560                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7561                 else      
7562                         aopPut(AOP(result),"a",MSB24+offr);
7563         }
7564         
7565         if(size > MSB32+offr){
7566                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7567                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7568                         MOVA(l);  
7569                 }
7570                 pic14_emitcode("rlc","a");
7571                 aopPut(AOP(result),"a",MSB32+offr);
7572         }
7573         if(offr != LSB)
7574                 aopPut(AOP(result),zero,LSB);       
7575 }
7576
7577 /*-----------------------------------------------------------------*/
7578 /* genlshFour - shift four byte by a known amount != 0             */
7579 /*-----------------------------------------------------------------*/
7580 static void genlshFour (operand *result, operand *left, int shCount)
7581 {
7582         int size;
7583         
7584         FENTRY;
7585         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7586         size = AOP_SIZE(result);
7587         
7588         /* if shifting more that 3 bytes */
7589         if (shCount >= 24 ) {
7590                 shCount -= 24;
7591                 if (shCount)
7592                 /* lowest order of left goes to the highest
7593                 order of the destination */
7594                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7595                 else
7596                         movLeft2Result(left, LSB, result, MSB32);
7597                 aopPut(AOP(result),zero,LSB);
7598                 aopPut(AOP(result),zero,MSB16);
7599                 aopPut(AOP(result),zero,MSB32);
7600                 return;
7601         }
7602         
7603         /* more than two bytes */
7604         else if ( shCount >= 16 ) {
7605                 /* lower order two bytes goes to higher order two bytes */
7606                 shCount -= 16;
7607                 /* if some more remaining */
7608                 if (shCount)
7609                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7610                 else {
7611                         movLeft2Result(left, MSB16, result, MSB32);
7612                         movLeft2Result(left, LSB, result, MSB24);
7613                 }
7614                 aopPut(AOP(result),zero,MSB16);
7615                 aopPut(AOP(result),zero,LSB);
7616                 return;
7617         }    
7618         
7619         /* if more than 1 byte */
7620         else if ( shCount >= 8 ) {
7621                 /* lower order three bytes goes to higher order  three bytes */
7622                 shCount -= 8;
7623                 if(size == 2){
7624                         if(shCount)
7625                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7626                         else
7627                                 movLeft2Result(left, LSB, result, MSB16);
7628                 }
7629                 else{   /* size = 4 */
7630                         if(shCount == 0){
7631                                 movLeft2Result(left, MSB24, result, MSB32);
7632                                 movLeft2Result(left, MSB16, result, MSB24);
7633                                 movLeft2Result(left, LSB, result, MSB16);
7634                                 aopPut(AOP(result),zero,LSB);
7635                         }
7636                         else if(shCount == 1)
7637                                 shiftLLong(left, result, MSB16);
7638                         else{
7639                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7640                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7641                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7642                                 aopPut(AOP(result),zero,LSB);
7643                         }
7644                 }
7645         }
7646         
7647         /* 1 <= shCount <= 7 */
7648         else if(shCount <= 2){
7649                 shiftLLong(left, result, LSB);
7650                 if(shCount == 2)
7651                         shiftLLong(result, result, LSB);
7652         }
7653         /* 3 <= shCount <= 7, optimize */
7654         else{
7655                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7656                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7657                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7658         }
7659 }
7660 #endif
7661
7662 #if 0
7663 /*-----------------------------------------------------------------*/
7664 /* genLeftShiftLiteral - left shifting by known count              */
7665 /*-----------------------------------------------------------------*/
7666 static void genLeftShiftLiteral (operand *left,
7667                                                                  operand *right,
7668                                                                  operand *result,
7669                                                                  iCode *ic)
7670 {    
7671         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7672         //int size;
7673         
7674         FENTRY;
7675         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7676         freeAsmop(right,NULL,ic,TRUE);
7677         
7678         aopOp(left,ic,FALSE);
7679         aopOp(result,ic,FALSE);
7680
7681         size = getSize(operandType(result));
7682         
7683 #if VIEW_SIZE
7684         pic14_emitcode("; shift left ","result %d, left %d",size,
7685                 AOP_SIZE(left));
7686 #endif
7687         
7688         /* I suppose that the left size >= result size */
7689         if(shCount == 0){
7690                 while(size--){
7691                         movLeft2Result(left, size, result, size);
7692                 }
7693         }
7694         
7695         else if(shCount >= (size * 8))
7696                 while(size--)
7697                         aopPut(AOP(result),zero,size);
7698                 else{
7699                         switch (size) {
7700                         case 1:
7701                                 genlshOne (result,left,shCount);
7702                                 break;
7703                                 
7704                         case 2:
7705                         case 3:
7706                                 genlshTwo (result,left,shCount);
7707                                 break;
7708                                 
7709                         case 4:
7710                                 genlshFour (result,left,shCount);
7711                                 break;
7712                         }
7713                 }
7714                 freeAsmop(left,NULL,ic,TRUE);
7715                 freeAsmop(result,NULL,ic,TRUE);
7716 }
7717 #endif
7718
7719 /*-----------------------------------------------------------------*
7720 * genMultiAsm - repeat assembly instruction for size of register.
7721 * if endian == 1, then the high byte (i.e base address + size of 
7722 * register) is used first else the low byte is used first;
7723 *-----------------------------------------------------------------*/
7724 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7725 {
7726         
7727         int offset = 0;
7728         
7729         FENTRY;
7730         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7731         
7732         if(!reg)
7733                 return;
7734         
7735         if(!endian) {
7736                 endian = 1;
7737         } else {
7738                 endian = -1;
7739                 offset = size-1;
7740         }
7741         
7742         while(size--) {
7743                 emitpcode(poc,    popGet(AOP(reg),offset));
7744                 offset += endian;
7745         }
7746         
7747 }
7748
7749 #if 0
7750 /*-----------------------------------------------------------------*/
7751 /* genLeftShift - generates code for left shifting                 */
7752 /*-----------------------------------------------------------------*/
7753 static void genLeftShift (iCode *ic)
7754 {
7755         operand *left,*right, *result;
7756         int size, offset;
7757         unsigned long lit = 0L;
7758         char *l;
7759         symbol *tlbl , *tlbl1;
7760         pCodeOp *pctemp;
7761         
7762         FENTRY;
7763         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7764         
7765         right = IC_RIGHT(ic);
7766         left  = IC_LEFT(ic);
7767         result = IC_RESULT(ic);
7768         
7769         aopOp(right,ic,FALSE);
7770         aopOp(left,ic,FALSE);
7771         aopOp(result,ic,FALSE);
7772         
7773         
7774         /* if the shift count is known then do it 
7775         as efficiently as possible */
7776         if (AOP_TYPE(right) == AOP_LIT) {
7777                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7778                 return ;
7779         }
7780         
7781         /* shift count is unknown then we have to form 
7782         a loop get the loop count in B : Note: we take
7783         only the lower order byte since shifting
7784         more that 32 bits make no sense anyway, ( the
7785         largest size of an object can be only 32 bits ) */  
7786         
7787         /* this code fails for RIGHT == RESULT */
7788         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7789         
7790         /* now move the left to the result if they are not the
7791         same */
7792         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7793                 AOP_SIZE(result) > 1) {
7794                 
7795                 size = AOP_SIZE(result);
7796                 offset=0;
7797                 while (size--) {
7798                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7799                         if (*l == '@' && (IS_AOP_PREG(result))) {
7800                                 
7801                                 pic14_emitcode("mov","a,%s",l);
7802                                 aopPut(AOP(result),"a",offset);
7803                         } else {
7804                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7805                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7806                                 //aopPut(AOP(result),l,offset);
7807                         }
7808                         offset++;
7809                 }
7810         }
7811         
7812         if(AOP_TYPE(left) == AOP_LIT)
7813                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7814
7815         size = AOP_SIZE(result);
7816         
7817         /* if it is only one byte then */
7818         if (size == 1) {
7819                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7820                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7821                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7822                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7823                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7824                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7825                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7826                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7827                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7828                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7829                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7830                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7831                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7832                 } else {
7833                         
7834                         tlbl = newiTempLabel(NULL);
7835                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7836                                 mov2w (AOP(left), 0);
7837                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7838                         }
7839                         
7840                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7841                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7842                         emitpLabel(tlbl->key);
7843                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7844                         emitpcode(POC_ADDLW,  popGetLit(1));
7845                         emitSKPC;
7846                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7847                 }
7848                 goto release ;
7849         }
7850         
7851         if (pic14_sameRegs(AOP(left),AOP(result))) {
7852                 
7853                 tlbl = newiTempLabel(NULL);
7854                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7855                 genMultiAsm(POC_RRF, result, size,1);
7856                 emitpLabel(tlbl->key);
7857                 genMultiAsm(POC_RLF, result, size,0);
7858                 emitpcode(POC_ADDLW,  popGetLit(1));
7859                 emitSKPC;
7860                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7861                 goto release;
7862         }
7863         
7864         //tlbl = newiTempLabel(NULL);
7865         //offset = 0 ;   
7866         //tlbl1 = newiTempLabel(NULL);
7867         
7868         //reAdjustPreg(AOP(result));    
7869         
7870         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7871         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7872         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7873         //MOVA(l);
7874         //pic14_emitcode("add","a,acc");         
7875         //aopPut(AOP(result),"a",offset++);
7876         //while (--size) {
7877         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7878         //  MOVA(l);
7879         //  pic14_emitcode("rlc","a");         
7880         //  aopPut(AOP(result),"a",offset++);
7881         //}
7882         //reAdjustPreg(AOP(result));
7883         
7884         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7885         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7886         
7887         
7888         tlbl = newiTempLabel(NULL);
7889         tlbl1= newiTempLabel(NULL);
7890         
7891         size = AOP_SIZE(result);
7892         offset = 1;
7893         
7894         pctemp = popGetTempReg();  /* grab a temporary working register. */
7895         
7896         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7897         
7898         /* offset should be 0, 1 or 3 */
7899         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7900         emitSKPNZ;
7901         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7902         
7903         emitpcode(POC_MOVWF, pctemp);
7904         
7905         
7906         emitpLabel(tlbl->key);
7907         
7908         emitCLRC;
7909         emitpcode(POC_RLF,  popGet(AOP(result),0));
7910         while(--size)
7911                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7912         
7913         emitpcode(POC_DECFSZ,  pctemp);
7914         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7915         emitpLabel(tlbl1->key);
7916         
7917         popReleaseTempReg(pctemp);
7918         
7919         
7920 release:
7921         freeAsmop (right,NULL,ic,TRUE);
7922         freeAsmop(left,NULL,ic,TRUE);
7923         freeAsmop(result,NULL,ic,TRUE);
7924 }
7925 #endif
7926
7927 #if 0
7928 /*-----------------------------------------------------------------*/
7929 /* genrshOne - right shift a one byte quantity by known count      */
7930 /*-----------------------------------------------------------------*/
7931 static void genrshOne (operand *result, operand *left,
7932                                            int shCount, int sign)
7933 {
7934         FENTRY;
7935         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7936         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7937 }
7938
7939 /*-----------------------------------------------------------------*/
7940 /* genrshTwo - right shift two bytes by known amount != 0          */
7941 /*-----------------------------------------------------------------*/
7942 static void genrshTwo (operand *result,operand *left,
7943                                            int shCount, int sign)
7944 {
7945         FENTRY;
7946         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7947         /* if shCount >= 8 */
7948         if (shCount >= 8) {
7949                 shCount -= 8 ;
7950                 if (shCount)
7951                         shiftR1Left2Result(left, MSB16, result, LSB,
7952                         shCount, sign);
7953                 else
7954                         movLeft2Result(left, MSB16, result, LSB);
7955                 
7956                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7957                 
7958                 if(sign) {
7959                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7960                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7961                 }
7962         }
7963         
7964         /*  1 <= shCount <= 7 */
7965         else
7966                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7967 }
7968
7969 /*-----------------------------------------------------------------*/
7970 /* shiftRLong - shift right one long from left to result           */
7971 /* offl = LSB or MSB16                                             */
7972 /*-----------------------------------------------------------------*/
7973 static void shiftRLong (operand *left, int offl,
7974                                                 operand *result, int sign)
7975 {
7976         int size, same;
7977         
7978         FENTRY;
7979         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7980         
7981         size = AOP_SIZE(left);
7982         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7983         
7984         if (sign)
7985                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7986         else
7987                 emitCLRC;
7988
7989         assert (offl >= 0 && offl < size);
7990
7991         same = pic14_sameRegs (AOP(left), AOP(result));
7992
7993         /* perform the shift */
7994         while (size--)
7995         {
7996                 if (same && !offl) {
7997                         emitpcode (POC_RRF, popGet (AOP(result), size));
7998                 } else {
7999                         emitpcode (POC_RRFW, popGet (AOP(left), size));
8000                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
8001                 }
8002         } // while
8003
8004         addSign (result, AOP_SIZE(left) - offl, sign);
8005 }
8006
8007 /*-----------------------------------------------------------------*/
8008 /* genrshFour - shift four byte by a known amount != 0             */
8009 /*-----------------------------------------------------------------*/
8010 static void genrshFour (operand *result, operand *left,
8011                                                 int shCount, int sign)
8012 {
8013         FENTRY;
8014         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8015         /* if shifting more that 3 bytes */
8016         if(shCount >= 24 ) {
8017                 shCount -= 24;
8018                 if(shCount)
8019                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8020                 else
8021                         movLeft2Result(left, MSB32, result, LSB);
8022                 
8023                 addSign(result, MSB16, sign);
8024         }
8025         else if(shCount >= 16){
8026                 shCount -= 16;
8027                 if(shCount)
8028                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8029                 else{
8030                         movLeft2Result(left, MSB24, result, LSB);
8031                         movLeft2Result(left, MSB32, result, MSB16);
8032                 }
8033                 addSign(result, MSB24, sign);
8034         }
8035         else if(shCount >= 8){
8036                 shCount -= 8;
8037                 if(shCount == 1)
8038                         shiftRLong(left, MSB16, result, sign);
8039                 else if(shCount == 0){
8040                         movLeft2Result(left, MSB16, result, LSB);
8041                         movLeft2Result(left, MSB24, result, MSB16);
8042                         movLeft2Result(left, MSB32, result, MSB24);
8043                         addSign(result, MSB32, sign);
8044                 }
8045                 else{
8046                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8047                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8048                         /* the last shift is signed */
8049                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8050                         addSign(result, MSB32, sign);
8051                 }
8052         }
8053         else{   /* 1 <= shCount <= 7 */
8054                 if(shCount <= 2){
8055                         shiftRLong(left, LSB, result, sign);
8056                         if(shCount == 2)
8057                                 shiftRLong(result, LSB, result, sign);
8058                 }
8059                 else{
8060                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8061                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8062                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8063                 }
8064         }
8065 }
8066
8067 /*-----------------------------------------------------------------*/
8068 /* genRightShiftLiteral - right shifting by known count            */
8069 /*-----------------------------------------------------------------*/
8070 static void genRightShiftLiteral (operand *left,
8071                                                                   operand *right,
8072                                                                   operand *result,
8073                                                                   iCode *ic,
8074                                                                   int sign)
8075 {    
8076         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8077         int lsize,res_size;
8078         
8079         FENTRY;
8080         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8081         freeAsmop(right,NULL,ic,TRUE);
8082         
8083         aopOp(left,ic,FALSE);
8084         aopOp(result,ic,FALSE);
8085         
8086 #if VIEW_SIZE
8087         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8088                 AOP_SIZE(left));
8089 #endif
8090         
8091         lsize = pic14_getDataSize(left);
8092         res_size = pic14_getDataSize(result);
8093         /* test the LEFT size !!! */
8094         
8095         /* I suppose that the left size >= result size */
8096         if(shCount == 0){
8097                 while(res_size--)
8098                         movLeft2Result(left, res_size, result, res_size);
8099         }
8100         
8101         else if(shCount >= (lsize * 8)){
8102                 
8103                 if(res_size == 1) {
8104                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8105                         if(sign) {
8106                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8107                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8108                         }
8109                 } else {
8110                         
8111                         if(sign) {
8112                                 emitpcode(POC_MOVLW, popGetLit(0));
8113                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8114                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8115                                 while(res_size--)
8116                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8117                                 
8118                         } else {
8119                                 
8120                                 while(res_size--)
8121                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8122                         }
8123                 }
8124         } else {
8125                 
8126                 switch (res_size) {
8127                 case 1:
8128                         genrshOne (result,left,shCount,sign);
8129                         break;
8130                         
8131                 case 2:
8132                         genrshTwo (result,left,shCount,sign);
8133                         break;
8134                         
8135                 case 4:
8136                         genrshFour (result,left,shCount,sign);
8137                         break;
8138                 default :
8139                         break;
8140                 }
8141                 
8142         }
8143
8144         freeAsmop(left,NULL,ic,TRUE);
8145         freeAsmop(result,NULL,ic,TRUE);
8146 }
8147 #endif
8148
8149 #if 0
8150 /*-----------------------------------------------------------------*/
8151 /* genSignedRightShift - right shift of signed number              */
8152 /*-----------------------------------------------------------------*/
8153 static void genSignedRightShift (iCode *ic)
8154 {
8155         operand *right, *left, *result;
8156         int size, offset;
8157         //  char *l;
8158         symbol *tlbl, *tlbl1 ;
8159         pCodeOp *pctemp;
8160         
8161         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8162         
8163         /* we do it the hard way put the shift count in b
8164         and loop thru preserving the sign */
8165         FENTRY;
8166         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8167         
8168         right = IC_RIGHT(ic);
8169         left  = IC_LEFT(ic);
8170         result = IC_RESULT(ic);
8171         
8172         aopOp(right,ic,FALSE);  
8173         aopOp(left,ic,FALSE);
8174         aopOp(result,ic,FALSE);
8175         
8176         
8177         if ( AOP_TYPE(right) == AOP_LIT) {
8178                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8179                 //genRightShiftLiteral (left,right,result,ic,1);
8180                 return ;
8181         }
8182         /* shift count is unknown then we have to form 
8183         a loop get the loop count in B : Note: we take
8184         only the lower order byte since shifting
8185         more that 32 bits make no sense anyway, ( the
8186         largest size of an object can be only 32 bits ) */  
8187         
8188         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8189         //pic14_emitcode("inc","b");
8190         //freeAsmop (right,NULL,ic,TRUE);
8191         //aopOp(left,ic,FALSE);
8192         //aopOp(result,ic,FALSE);
8193         
8194         /* now move the left to the result if they are not the
8195         same */
8196         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8197                 AOP_SIZE(result) > 1) {
8198                 
8199                 size = AOP_SIZE(result);
8200                 offset=0;
8201                 while (size--) { 
8202                         /*
8203                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8204                         if (*l == '@' && IS_AOP_PREG(result)) {
8205                                 pic14_emitcode("mov","a,%s",l);
8206                                 aopPut(AOP(result),"a",offset);
8207                         } else
8208                         aopPut(AOP(result),l,offset);
8209                         */
8210                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8211                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8212                         
8213                         offset++;
8214                 }
8215         }
8216         
8217         /* mov the highest order bit to OVR */    
8218         tlbl = newiTempLabel(NULL);
8219         tlbl1= newiTempLabel(NULL);
8220         
8221         size = AOP_SIZE(result);
8222         offset = size - 1;
8223         
8224         pctemp = popGetTempReg();  /* grab a temporary working register. */
8225         
8226         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8227         
8228         /* offset should be 0, 1 or 3 */
8229         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8230         emitSKPNZ;
8231         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8232         
8233         emitpcode(POC_MOVWF, pctemp);
8234         
8235         
8236         emitpLabel(tlbl->key);
8237         
8238         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8239         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8240         
8241         while(--size) {
8242                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8243         }
8244         
8245         emitpcode(POC_DECFSZ,  pctemp);
8246         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8247         emitpLabel(tlbl1->key);
8248         
8249         popReleaseTempReg(pctemp);
8250 #if 0
8251         size = AOP_SIZE(result);
8252         offset = size - 1;
8253         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8254         pic14_emitcode("rlc","a");
8255         pic14_emitcode("mov","ov,c");
8256         /* if it is only one byte then */
8257         if (size == 1) {
8258                 l = aopGet(AOP(left),0,FALSE,FALSE);
8259                 MOVA(l);
8260                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8261                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8262                 pic14_emitcode("mov","c,ov");
8263                 pic14_emitcode("rrc","a");
8264                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8265                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8266                 aopPut(AOP(result),"a",0);
8267                 goto release ;
8268         }
8269         
8270         reAdjustPreg(AOP(result));
8271         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8272         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8273         pic14_emitcode("mov","c,ov");
8274         while (size--) {
8275                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8276                 MOVA(l);
8277                 pic14_emitcode("rrc","a");         
8278                 aopPut(AOP(result),"a",offset--);
8279         }
8280         reAdjustPreg(AOP(result));
8281         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8282         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8283         
8284 release:
8285 #endif
8286         
8287         freeAsmop(left,NULL,ic,TRUE);
8288         freeAsmop(result,NULL,ic,TRUE);
8289         freeAsmop(right,NULL,ic,TRUE);
8290 }
8291 #endif
8292
8293 /*-----------------------------------------------------------------*/
8294 /* loadSignToC - load the operand's sign bit into CARRY            */
8295 /*-----------------------------------------------------------------*/
8296
8297 static void loadSignToC (operand *op)
8298 {
8299         FENTRY;
8300         assert (op && AOP(op) && AOP_SIZE(op));
8301
8302         emitCLRC;
8303         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8304         emitSETC;
8305 }
8306
8307 /*-----------------------------------------------------------------*/
8308 /* genRightShift - generate code for right shifting                */
8309 /*-----------------------------------------------------------------*/
8310 static void genGenericShift (iCode *ic, int shiftRight)
8311 {
8312         operand *right, *left, *result;
8313         sym_link *retype ;
8314         int size;
8315         symbol *tlbl, *tlbl1, *inverselbl;
8316         
8317         FENTRY;
8318         /* if signed then we do it the hard way preserve the
8319         sign bit moving it inwards */
8320         retype = getSpec(operandType(IC_RESULT(ic)));
8321         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8322         
8323         /* signed & unsigned types are treated the same : i.e. the
8324         signed is NOT propagated inwards : quoting from the
8325         ANSI - standard : "for E1 >> E2, is equivalent to division
8326         by 2**E2 if unsigned or if it has a non-negative value,
8327         otherwise the result is implementation defined ", MY definition
8328         is that the sign does not get propagated */
8329         
8330         right = IC_RIGHT(ic);
8331         left  = IC_LEFT(ic);
8332         result = IC_RESULT(ic);
8333         
8334         aopOp(right,ic,FALSE);
8335         aopOp(left,ic,FALSE);
8336         aopOp(result,ic,FALSE);
8337         
8338         /* if the shift count is known then do it 
8339         as efficiently as possible */
8340         if (AOP_TYPE(right) == AOP_LIT) {
8341                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8342                 if (lit < 0)
8343                 {
8344                         lit = -lit;
8345                         shiftRight = !shiftRight;
8346                 }
8347                 
8348                 if (shiftRight)
8349                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8350                 else
8351                         shiftLeft_Left2ResultLit (left, result, lit);
8352                 //genRightShiftLiteral (left,right,result,ic, 0);
8353                 return ;
8354         }
8355         
8356         /* shift count is unknown then we have to form 
8357         a loop get the loop count in B : Note: we take
8358         only the lower order byte since shifting
8359         more that 32 bits make no sense anyway, ( the
8360         largest size of an object can be only 32 bits ) */  
8361
8362         /* we must not overwrite the shift counter */
8363         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8364         
8365         /* now move the left to the result if they are not the
8366         same */
8367         if (!pic14_sameRegs(AOP(left),AOP(result)))
8368         {
8369                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8370                 while (size--) {
8371                         mov2w(AOP(left), size);
8372                         movwf(AOP(result), size);
8373                 }
8374                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8375         }
8376         
8377         tlbl = newiTempLabel(NULL);
8378         tlbl1= newiTempLabel(NULL);
8379         inverselbl = NULL;
8380         size = AOP_SIZE(result);
8381
8382         mov2w(AOP(right),0);
8383         if (!SPEC_USIGN(operandType(right)))
8384         {
8385                 inverselbl = newiTempLabel(NULL);
8386                 /* signed shift count -- invert shift direction for c<0 */
8387                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8388                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8389         } // if
8390         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8391         /* check for `a = b >> c' with `-c == 0' */
8392         emitSKPNZ;
8393         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8394         emitpLabel(tlbl->key);
8395         /* propagate the sign bit inwards for SIGNED result */
8396         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8397         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8398         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8399         emitSKPC;
8400         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8401
8402         if (!SPEC_USIGN(operandType(right)))
8403         {
8404                 symbol *inv_loop = newiTempLabel(NULL);
8405
8406                 shiftRight = !shiftRight;       /* invert shift direction */
8407                 
8408                 /* we came here from the code above -- we are done */
8409                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8410                 
8411                 /* emit code for shifting N<0 steps, count is already in W */
8412                 emitpLabel(inverselbl->key);
8413                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8414                 emitpLabel(inv_loop->key);
8415                 /* propagate the sign bit inwards for SIGNED result */
8416                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8417                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8418                 emitpcode(POC_ADDLW, popGetLit(1));
8419                 emitSKPC;
8420                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8421         } // if
8422         
8423         emitpLabel(tlbl1->key);
8424         
8425         freeAsmop(left,NULL,ic,TRUE);
8426         freeAsmop (right,NULL,ic,TRUE);
8427         freeAsmop(result,NULL,ic,TRUE);
8428 }
8429
8430 static void genRightShift (iCode *ic)
8431 {
8432         genGenericShift(ic, 1);
8433 }
8434
8435 static void genLeftShift (iCode *ic)
8436 {
8437         genGenericShift(ic, 0);
8438 }
8439
8440 /*-----------------------------------------------------------------*/
8441 /* SetIrp - Set IRP bit                                            */
8442 /*-----------------------------------------------------------------*/
8443 void SetIrp(operand *result) {
8444         FENTRY;
8445         if (AOP_TYPE(result) == AOP_LIT) {
8446                 unsigned lit = (unsigned)operandLitValue(result);
8447                 if (lit&0x100)
8448                         emitSETIRP;
8449                 else
8450                         emitCLRIRP;
8451         } else {
8452                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8453                         int addrs = PCOL(AOP(result))->lit;
8454                         if (addrs & 0x100)
8455                                 emitSETIRP;
8456                         else
8457                                 emitCLRIRP;
8458                 } else {
8459                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8460                         if(AOP_SIZE(result) > 1) {
8461                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8462                                 emitSETIRP;
8463                         }
8464                 }
8465         }
8466 }
8467
8468 static void
8469 setup_fsr (operand *ptr)
8470 {
8471   mov2w_op(ptr, 0);
8472   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8473
8474   /* also setup-up IRP */
8475   SetIrp (ptr);
8476 }
8477
8478 /*-----------------------------------------------------------------*/
8479 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8480 /*                  arbitrary pointer (__code, __data, generic)    */
8481 /*-----------------------------------------------------------------*/
8482 static void
8483 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8484 {
8485     FENTRY;
8486     switch (p_type)
8487     {
8488     case POINTER:
8489     case FPOINTER:
8490       if (!alreadyAddressed) setup_fsr (src);
8491       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8492       break;
8493     
8494     case CPOINTER:
8495       assert( AOP_SIZE(src) == 2 );
8496       mov2w_op(src, 0);
8497       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8498       mov2w_op(src, 1);
8499       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8500       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8501       call_libraryfunc ("__gptrget1");
8502       break;
8503     
8504     case GPOINTER:
8505       assert( AOP_SIZE(src) == 3 );
8506       mov2w_op(src, 0);
8507       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8508       mov2w_op(src, 1);
8509       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8510       mov2w_op(src, 2);
8511       call_libraryfunc ("__gptrget1");
8512       break;
8513     
8514     default:
8515       assert( !"unhandled pointer type" );
8516       break;
8517     }
8518 }
8519
8520 /*-----------------------------------------------------------------*/
8521 /* emitPtrByteSet - emits code to set a byte from src through a    */
8522 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8523 /*-----------------------------------------------------------------*/
8524 static void
8525 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8526 {
8527     FENTRY;
8528     switch (p_type)
8529     {
8530     case POINTER:
8531     case FPOINTER:
8532       if (!alreadyAddressed) setup_fsr (dst);
8533       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8534       break;
8535     
8536     case CPOINTER:
8537       assert( !"trying to assign to __code pointer" );
8538       break;
8539     
8540     case GPOINTER:
8541       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8542       mov2w_op(dst, 0);
8543       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8544       mov2w_op(dst, 1);
8545       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8546       mov2w_op(dst, 2);
8547       call_libraryfunc ("__gptrput1");
8548       break;
8549
8550     default:
8551       assert( !"unhandled pointer type" );
8552       break;
8553     }
8554 }
8555
8556 /*-----------------------------------------------------------------*/
8557 /* genUnpackBits - generates code for unpacking bits               */
8558 /*-----------------------------------------------------------------*/
8559 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8560 {    
8561   int rsize;            /* result size */
8562   sym_link *etype;      /* bitfield type information */
8563   int blen;             /* bitfield length */
8564   int bstr;             /* bitfield starting bit within byte */
8565
8566   FENTRY;
8567   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8568   etype = getSpec(operandType(result));
8569   rsize = getSize (operandType (result));
8570   blen = SPEC_BLEN (etype);
8571   bstr = SPEC_BSTR (etype);
8572
8573   /* single bit field case */
8574   if (blen == 1) {
8575     if (ifx) { /* that is for an if statement */
8576       pCodeOp *pcop;
8577       resolvedIfx rIfx;
8578       resolveIfx(&rIfx,ifx);
8579       if (ptype == -1) /* direct */
8580         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8581       else
8582         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8583       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8584       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8585       ifx->generated=1;
8586     } else {
8587       int i;
8588       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8589       for (i=0; i < AOP_SIZE(result); i++)
8590         emitpcode (POC_CLRF, popGet (AOP(result), i));
8591
8592       switch (ptype)
8593       {
8594       case -1:
8595         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8596         /* adjust result below */
8597         break;
8598         
8599       case POINTER:
8600       case FPOINTER:
8601       case GPOINTER:
8602       case CPOINTER:
8603         emitPtrByteGet (left, ptype, FALSE);
8604         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8605         emitSKPZ;
8606         /* adjust result below */
8607         break;
8608         
8609       default:
8610         assert( !"unhandled pointer type" );
8611       } // switch
8612
8613       /* move sign-/zero extended bit to result */
8614       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8615         emitpcode (POC_INCF, popGet (AOP(result), 0));
8616       } else {
8617         emitpcode (POC_DECF, popGet (AOP(result), 0));
8618       }
8619       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8620     }
8621     return;
8622   }
8623   else if (blen <= 8 && ((blen + bstr) <= 8))
8624   {
8625     /* blen > 1 */
8626     int i;
8627
8628     for (i=0; i < AOP_SIZE(result); i++)
8629       emitpcode (POC_CLRF, popGet (AOP(result), i));
8630
8631     switch (ptype)
8632     {
8633     case -1:
8634       mov2w(AOP(left), 0);
8635       break;
8636       
8637     case POINTER:
8638     case FPOINTER:
8639     case GPOINTER:
8640     case CPOINTER:
8641       emitPtrByteGet (left, ptype, FALSE);
8642       break;
8643       
8644     default:
8645       assert( !"unhandled pointer type" );
8646     } // switch
8647
8648     if (blen < 8)
8649       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8650     movwf(AOP(result), 0);
8651     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8652
8653     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8654     {
8655       /* signed bitfield */
8656       assert (bstr + blen > 0);
8657       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8658       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8659       emitpcode(POC_IORWF, popGet(AOP(result),0));
8660     }
8661     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8662     return;
8663   }
8664
8665   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8666 }
8667
8668 #if 1
8669 /*-----------------------------------------------------------------*/
8670 /* genDataPointerGet - generates code when ptr offset is known     */
8671 /*-----------------------------------------------------------------*/
8672 static void genDataPointerGet (operand *left, 
8673         operand *result, 
8674         iCode *ic)
8675 {
8676         int size , offset = 0;
8677                 
8678         FENTRY;
8679         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8680         
8681         
8682         /* optimization - most of the time, left and result are the same
8683         * address, but different types. for the pic code, we could omit
8684         * the following
8685         */
8686         aopOp(result,ic,TRUE);
8687         
8688         if (pic14_sameRegs (AOP(left), AOP(result)))
8689                 return;
8690         
8691         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8692         
8693         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8694         
8695         size = AOP_SIZE(result);
8696         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8697         
8698         offset = 0;
8699         while (size--) {
8700                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8701                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8702                 offset++;
8703         }
8704         
8705         freeAsmop(left,NULL,ic,TRUE);
8706         freeAsmop(result,NULL,ic,TRUE);
8707 }
8708 #endif
8709
8710 /*-----------------------------------------------------------------*/
8711 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8712 /*-----------------------------------------------------------------*/
8713 static void genNearPointerGet (operand *left, 
8714                                                            operand *result, 
8715                                                            iCode *ic)
8716 {
8717         asmop *aop = NULL;
8718         sym_link *ltype = operandType(left);
8719         sym_link *rtype = operandType(result);
8720         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8721         int direct = 0;
8722
8723         FENTRY;
8724         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8725         
8726         
8727         aopOp(left,ic,FALSE);
8728         
8729         /* if left is rematerialisable and
8730         result is not bit variable type and
8731         the left is pointer to data space i.e
8732         lower 128 bytes of space */
8733         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8734                 !IS_BITVAR(retype)         &&
8735                 PIC_IS_DATA_PTR(ltype)) {
8736                 genDataPointerGet (left,result,ic);
8737                 return ;
8738         }
8739         
8740         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8741         aopOp (result,ic,FALSE);
8742         
8743         /* Check if can access directly instead of via a pointer */
8744         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8745                 && AOP_SIZE(result) == 1)
8746         {
8747                 direct = 1;
8748         }
8749
8750         if (IS_BITFIELD(getSpec(operandType(result)))) 
8751         {
8752                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8753                 goto release;
8754         }
8755         
8756         /* If the pointer value is not in a the FSR then need to put it in */
8757         /* Must set/reset IRP bit for use with FSR. */
8758         if (!direct)
8759           setup_fsr (left);
8760         
8761 //      sym_link *etype;
8762         /* if bitfield then unpack the bits */
8763         {
8764                 /* we have can just get the values */
8765                 int size = AOP_SIZE(result);
8766                 int offset = 0 ;  
8767                 
8768                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8769                 
8770                 while(size--) {
8771                         if (direct)
8772                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8773                         else
8774                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8775                         if (AOP_TYPE(result) == AOP_LIT) {
8776                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8777                         } else {
8778                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8779                         }
8780                         if (size && !direct)
8781                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8782                         offset++;
8783                 }
8784         }
8785         
8786         /* now some housekeeping stuff */
8787         if (aop) {
8788                 /* we had to allocate for this iCode */
8789                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8790                 freeAsmop(NULL,aop,ic,TRUE);
8791         } else { 
8792                 /* we did not allocate which means left
8793                 already in a pointer register, then
8794                 if size > 0 && this could be used again
8795                 we have to point it back to where it 
8796                 belongs */
8797                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8798                 if (AOP_SIZE(result) > 1 &&
8799                         !OP_SYMBOL(left)->remat &&
8800                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8801                         ic->depth )) {
8802                         int size = AOP_SIZE(result) - 1;
8803                         while (size--)
8804                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8805                 }
8806         }
8807         
8808 release:
8809         /* done */
8810         freeAsmop(left,NULL,ic,TRUE);
8811         freeAsmop(result,NULL,ic,TRUE);
8812
8813 }
8814
8815 #if 0
8816 /*-----------------------------------------------------------------*/
8817 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8818 /*-----------------------------------------------------------------*/
8819 static void genPagedPointerGet (operand *left, 
8820                                                                 operand *result, 
8821                                                                 iCode *ic)
8822 {
8823         asmop *aop = NULL;
8824         regs *preg = NULL ;
8825         char *rname ;
8826         sym_link *rtype, *retype;    
8827         
8828         FENTRY;
8829         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8830         
8831         rtype = operandType(result);
8832         retype= getSpec(rtype);
8833         
8834         aopOp(left,ic,FALSE);
8835         
8836         /* if the value is already in a pointer register
8837         then don't need anything more */
8838         if (!AOP_INPREG(AOP(left))) {
8839                 /* otherwise get a free pointer register */
8840                 aop = newAsmop(0);
8841                 preg = getFreePtr(ic,&aop,FALSE);
8842                 pic14_emitcode("mov","%s,%s",
8843                         preg->name,
8844                         aopGet(AOP(left),0,FALSE,TRUE));
8845                 rname = preg->name ;
8846         } else
8847                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8848         
8849         freeAsmop(left,NULL,ic,TRUE);
8850         aopOp (result,ic,FALSE);
8851         
8852         /* if bitfield then unpack the bits */
8853         if (IS_BITFIELD(retype)) 
8854                 genUnpackBits (result,left,rname,PPOINTER,0);
8855         else {
8856                 /* we have can just get the values */
8857                 int size = AOP_SIZE(result);
8858                 int offset = 0 ;  
8859                 
8860                 while (size--) {
8861                         
8862                         pic14_emitcode("movx","a,@%s",rname);
8863                         aopPut(AOP(result),"a",offset);
8864                         
8865                         offset++ ;
8866                         
8867                         if (size)
8868                                 pic14_emitcode("inc","%s",rname);
8869                 }
8870         }
8871         
8872         /* now some housekeeping stuff */
8873         if (aop) {
8874                 /* we had to allocate for this iCode */
8875                 freeAsmop(NULL,aop,ic,TRUE);
8876         } else { 
8877         /* we did not allocate which means left
8878         already in a pointer register, then
8879         if size > 0 && this could be used again
8880         we have to point it back to where it 
8881                 belongs */
8882                 if (AOP_SIZE(result) > 1 &&
8883                         !OP_SYMBOL(left)->remat &&
8884                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8885                         ic->depth )) {
8886                         int size = AOP_SIZE(result) - 1;
8887                         while (size--)
8888                                 pic14_emitcode("dec","%s",rname);
8889                 }
8890         }
8891         
8892         /* done */
8893         freeAsmop(result,NULL,ic,TRUE);
8894         
8895         
8896 }
8897
8898 /*-----------------------------------------------------------------*/
8899 /* genFarPointerGet - gget value from far space                    */
8900 /*-----------------------------------------------------------------*/
8901 static void genFarPointerGet (operand *left,
8902                                                           operand *result, iCode *ic)
8903 {
8904         int size, offset ;
8905         sym_link *retype = getSpec(operandType(result));
8906         
8907         FENTRY;
8908         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8909         
8910         aopOp(left,ic,FALSE);
8911         
8912         /* if the operand is already in dptr 
8913         then we do nothing else we move the value to dptr */
8914         if (AOP_TYPE(left) != AOP_STR) {
8915                 /* if this is remateriazable */
8916                 if (AOP_TYPE(left) == AOP_IMMD)
8917                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8918                 else { /* we need to get it byte by byte */
8919                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8920                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8921                         if (options.model == MODEL_FLAT24)
8922                         {
8923                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8924                         }
8925                 }
8926         }
8927         /* so dptr know contains the address */
8928         freeAsmop(left,NULL,ic,TRUE);
8929         aopOp(result,ic,FALSE);
8930         
8931         /* if bit then unpack */
8932         if (IS_BITFIELD(retype)) 
8933                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8934         else {
8935                 size = AOP_SIZE(result);
8936                 offset = 0 ;
8937                 
8938                 while (size--) {
8939                         pic14_emitcode("movx","a,@dptr");
8940                         aopPut(AOP(result),"a",offset++);
8941                         if (size)
8942                                 pic14_emitcode("inc","dptr");
8943                 }
8944         }
8945         
8946         freeAsmop(result,NULL,ic,TRUE);
8947 }
8948 #endif
8949
8950 #if 0
8951 /*-----------------------------------------------------------------*/
8952 /* genCodePointerGet - get value from code space                  */
8953 /*-----------------------------------------------------------------*/
8954 static void genCodePointerGet (operand *left,
8955                                                            operand *result, iCode *ic)
8956 {
8957         int size, offset ;
8958         sym_link *retype = getSpec(operandType(result));
8959         
8960         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8961         
8962         aopOp(left,ic,FALSE);
8963         
8964         /* if the operand is already in dptr 
8965         then we do nothing else we move the value to dptr */
8966         if (AOP_TYPE(left) != AOP_STR) {
8967                 /* if this is remateriazable */
8968                 if (AOP_TYPE(left) == AOP_IMMD)
8969                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8970                 else { /* we need to get it byte by byte */
8971                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8972                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8973                         if (options.model == MODEL_FLAT24)
8974                         {
8975                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8976                         }
8977                 }
8978         }
8979         /* so dptr know contains the address */
8980         freeAsmop(left,NULL,ic,TRUE);
8981         aopOp(result,ic,FALSE);
8982         
8983         /* if bit then unpack */
8984         if (IS_BITFIELD(retype)) 
8985                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8986         else {
8987                 size = AOP_SIZE(result);
8988                 offset = 0 ;
8989                 
8990                 while (size--) {
8991                         pic14_emitcode("clr","a");
8992                         pic14_emitcode("movc","a,@a+dptr");
8993                         aopPut(AOP(result),"a",offset++);
8994                         if (size)
8995                                 pic14_emitcode("inc","dptr");
8996                 }
8997         }
8998         
8999         freeAsmop(result,NULL,ic,TRUE);
9000 }
9001 #endif
9002 /*-----------------------------------------------------------------*/
9003 /* genGenPointerGet - gget value from generic pointer space        */
9004 /*-----------------------------------------------------------------*/
9005 static void genGenPointerGet (operand *left,
9006                                                           operand *result, iCode *ic)
9007 {
9008         FENTRY;
9009         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9010         aopOp(left,ic,FALSE);
9011         aopOp(result,ic,FALSE);
9012         
9013         
9014         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9015
9016         if (IS_BITFIELD(getSpec(operandType(result))))
9017         {
9018           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
9019           return;
9020         }
9021
9022         {
9023           /* emit call to __gptrget */
9024           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9025           int size = AOP_SIZE(result);
9026           int idx = 0;
9027
9028           assert (size > 0 && size <= 4);
9029
9030           /* pass arguments */
9031           assert (AOP_SIZE(left) == 3);
9032           mov2w(AOP(left), 0);
9033           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9034           mov2w(AOP(left), 1);
9035           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9036           mov2w(AOP(left), 2);
9037           call_libraryfunc (func[size]);
9038           
9039           /* save result */
9040           movwf (AOP(result), --size);
9041           while (size--) {
9042             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9043             movwf (AOP(result), size);
9044           } // while
9045         }
9046         
9047         freeAsmop(left,NULL,ic,TRUE);
9048         freeAsmop(result,NULL,ic,TRUE);
9049         
9050 }
9051
9052 /*-----------------------------------------------------------------*/
9053 /* genConstPointerGet - get value from const generic pointer space */
9054 /*-----------------------------------------------------------------*/
9055 static void genConstPointerGet (operand *left,
9056                                                                 operand *result, iCode *ic)
9057 {
9058         //sym_link *retype = getSpec(operandType(result));
9059         #if 0
9060         symbol *albl, *blbl;//, *clbl;
9061         pCodeOp *pcop;
9062         #endif
9063         PIC_OPCODE poc;
9064         int i, size, lit;
9065         
9066         FENTRY;
9067         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9068         aopOp(left,ic,FALSE);
9069         aopOp(result,ic,FALSE);
9070         
9071         size = AOP_SIZE(result);
9072         
9073         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9074         
9075         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9076
9077         lit = op_isLitLike (left);
9078         poc = lit ? POC_MOVLW : POC_MOVFW;
9079
9080         if (IS_BITFIELD(getSpec(operandType(result))))
9081         {
9082                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9083                 goto release;
9084         }
9085
9086         {
9087                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9088                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9089                 assert (size > 0 && size <= 4);
9090                 
9091                 mov2w_op(left, 0);
9092                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9093                 mov2w_op(left, 1);
9094                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9095                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9096                 call_libraryfunc (func[size]);
9097
9098                 movwf(AOP(result),size-1);
9099                 for (i = 1; i < size; i++)
9100                 {
9101                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9102                         movwf(AOP(result),size - 1 - i);
9103                 } // for
9104         }
9105         
9106 release:
9107         freeAsmop(left,NULL,ic,TRUE);
9108         freeAsmop(result,NULL,ic,TRUE);
9109         
9110 }
9111 /*-----------------------------------------------------------------*/
9112 /* genPointerGet - generate code for pointer get                   */
9113 /*-----------------------------------------------------------------*/
9114 static void genPointerGet (iCode *ic)
9115 {
9116         operand *left, *result ;
9117         sym_link *type, *etype;
9118         int p_type = -1;
9119         
9120         FENTRY;
9121         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9122         
9123         left = IC_LEFT(ic);
9124         result = IC_RESULT(ic) ;
9125         
9126         /* depending on the type of pointer we need to
9127         move it to the correct pointer register */
9128         type = operandType(left);
9129         etype = getSpec(type);
9130         
9131         if (IS_PTR_CONST(type))
9132                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9133         
9134         /* if left is of type of pointer then it is simple */
9135         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9136                 p_type = DCL_TYPE(type);
9137         else {
9138                 /* we have to go by the storage class */
9139                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9140                 
9141                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9142                 
9143                 if (SPEC_OCLS(etype)->codesp ) {
9144                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9145                         //p_type = CPOINTER ; 
9146                 }
9147                 else
9148                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9149                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9150                         /*p_type = FPOINTER ;*/ 
9151                         else
9152                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9153                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9154                                 /*        p_type = PPOINTER; */
9155                                 else
9156                                         if (SPEC_OCLS(etype) == idata )
9157                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9158                                         /*      p_type = IPOINTER; */
9159                                         else
9160                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9161                                         /*      p_type = POINTER ; */
9162         }
9163         
9164         /* now that we have the pointer type we assign
9165         the pointer values */
9166         switch (p_type) {
9167                 
9168         case POINTER: 
9169         case FPOINTER:
9170         //case IPOINTER:
9171                 genNearPointerGet (left,result,ic);
9172                 break;
9173 /*
9174         case PPOINTER:
9175                 genPagedPointerGet(left,result,ic);
9176                 break;
9177                 
9178         case FPOINTER:
9179                 genFarPointerGet (left,result,ic);
9180                 break;
9181 */              
9182         case CPOINTER:
9183                 genConstPointerGet (left,result,ic);
9184                 break;
9185                 
9186         case GPOINTER:
9187                 genGenPointerGet (left,result,ic);
9188                 break;
9189         default:
9190                 assert ( !"unhandled pointer type" );
9191                 break;
9192         }
9193         
9194 }
9195
9196 /*-----------------------------------------------------------------*/
9197 /* genPackBits - generates code for packed bit storage             */
9198 /*-----------------------------------------------------------------*/
9199 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9200 {
9201   int blen;             /* bitfield length */
9202   int bstr;             /* bitfield starting bit within byte */
9203   int litval;           /* source literal value (if AOP_LIT) */
9204   unsigned char mask;   /* bitmask within current byte */
9205
9206   FENTRY;
9207   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9208
9209   blen = SPEC_BLEN (etype);
9210   bstr = SPEC_BSTR (etype);
9211
9212   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9213   if ((blen <= 8) && ((bstr + blen) <= 8))
9214   {
9215     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9216             (unsigned char) (0xFF >> (8 - bstr)));
9217
9218     if (AOP_TYPE (right) == AOP_LIT)
9219     {
9220       /* Case with a bitfield length <8 and literal source */
9221       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9222       if (blen == 1) {
9223         pCodeOp *pcop;
9224         
9225         switch (p_type)
9226         {
9227         case -1:
9228           if (AOP(result)->type == AOP_PCODE)
9229             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9230           else
9231             pcop = popGet(AOP(result),0);
9232           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9233           break;
9234         
9235         case POINTER:
9236         case FPOINTER:
9237           setup_fsr (result);
9238           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9239           break;
9240         
9241         case CPOINTER:
9242           assert( !"trying to assign to bitfield via pointer to __code space" );
9243           break;
9244         
9245         case GPOINTER:
9246           emitPtrByteGet(result, p_type, FALSE);
9247           if (lit) {
9248             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9249           } else {
9250             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9251           }
9252           emitPtrByteSet(result, p_type, TRUE);
9253           break;
9254         
9255         default:
9256           assert( !"unhandled pointer type" );
9257           break;
9258         } // switch (p_type)
9259       } else {
9260         /* blen > 1 */
9261         litval = lit << bstr;
9262         litval &= (~mask) & 0x00ff;
9263         
9264         switch (p_type)
9265         {
9266         case -1:
9267           mov2w (AOP(result), 0);
9268           if ((litval|mask) != 0x00ff)
9269             emitpcode(POC_ANDLW, popGetLit (mask));
9270           if (litval != 0x00)
9271             emitpcode(POC_IORLW, popGetLit (litval));
9272           movwf (AOP(result), 0);
9273           break;
9274         
9275         case POINTER:
9276         case FPOINTER:
9277         case GPOINTER:
9278           emitPtrByteGet(result, p_type, FALSE);
9279           if ((litval|mask) != 0x00ff)
9280             emitpcode(POC_ANDLW, popGetLit (mask));
9281           if (litval != 0x00)
9282             emitpcode(POC_IORLW, popGetLit (litval));
9283           emitPtrByteSet(result, p_type, TRUE);
9284           break;
9285         
9286         case CPOINTER:
9287           assert( !"trying to assign to bitfield via pointer to __code space" );
9288           break;
9289         
9290         default:
9291           assert( !"unhandled pointer type" );
9292           break;
9293         } // switch
9294       } // if (blen > 1)
9295     }
9296     else
9297     {
9298       /* right is no literal */
9299       if (blen==1) {
9300         switch (p_type)
9301         {
9302         case -1:
9303           /* Note more efficient code, of pre clearing bit then only setting it if required,
9304            * can only be done if it is known that the result is not a SFR */
9305           emitpcode(POC_RRFW,popGet(AOP(right),0));
9306           emitSKPC;
9307           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9308           emitSKPNC;
9309           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9310           break;
9311         
9312         case POINTER:
9313         case FPOINTER:
9314         case GPOINTER:
9315           emitPtrByteGet (result, p_type, FALSE);
9316           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9317           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9318           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9319           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9320           emitPtrByteSet (result, p_type, TRUE);
9321           break;
9322         
9323         case CPOINTER:
9324           assert( !"trying to assign to bitfield via pointer to __code space" );
9325           break;
9326         
9327         default:
9328           assert( !"unhandled pointer type" );
9329           break;
9330         } // switch
9331         return;
9332       } else {
9333         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9334         pCodeOp *temp = popGetTempReg ();
9335
9336         mov2w (AOP(right), 0);
9337         if (blen < 8) {
9338           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9339         }
9340         emitpcode(POC_MOVWF, temp);
9341         if (bstr) {
9342           AccLsh (temp, bstr);
9343         }
9344         
9345         switch (p_type)
9346         {
9347         case -1:
9348           mov2w (AOP(result), 0);
9349           emitpcode(POC_ANDLW, popGetLit (mask));
9350           emitpcode(POC_IORFW, temp);
9351           movwf (AOP(result), 0);
9352           break;
9353         
9354         case POINTER:
9355         case FPOINTER:
9356         case GPOINTER:
9357           emitPtrByteGet (result, p_type, FALSE);
9358           emitpcode(POC_ANDLW, popGetLit (mask));
9359           emitpcode(POC_IORFW, temp);
9360           emitPtrByteSet (result, p_type, TRUE);
9361           break;
9362         
9363         case CPOINTER:
9364           assert( !"trying to assign to bitfield via pointer to __code space" );
9365           break;
9366         
9367         default:
9368           assert( !"unhandled pointer type" );
9369           break;
9370         } // switch
9371
9372         popReleaseTempReg (temp);
9373       } // if (blen > 1)
9374     } // if (AOP(right)->type != AOP_LIT)
9375     return;
9376   } // if (blen <= 8 && ((blen + bstr) <= 8))
9377
9378   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9379 }
9380
9381 /*-----------------------------------------------------------------*/
9382 /* genDataPointerSet - remat pointer to data space                 */
9383 /*-----------------------------------------------------------------*/
9384 static void genDataPointerSet(operand *right,
9385         operand *result,
9386         iCode *ic)
9387 {
9388         int size, offset = 0 ;
9389         int ressize;
9390         
9391         FENTRY;
9392         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9393         aopOp(right,ic,FALSE);
9394         aopOp(result,ic,FALSE);
9395         
9396         assert (IS_SYMOP(result));
9397         assert (IS_PTR(OP_SYM_TYPE(result)));
9398         
9399         if (AOP_TYPE(right) == AOP_LIT)
9400           size = 4;
9401         else
9402           size = AOP_SIZE(right);
9403         ressize = getSize(OP_SYM_ETYPE(result));
9404         if (size > ressize) size = ressize;
9405         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9406         
9407         //assert( !"what's going on here?" );
9408
9409         /*
9410         if ( AOP_TYPE(result) == AOP_PCODE) {
9411         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9412         AOP(result)->aopu.pcop->name,
9413         PCOI(AOP(result)->aopu.pcop)->offset);
9414         }
9415         */
9416         
9417         // tsd, was l+1 - the underline `_' prefix was being stripped
9418         while (size--) {
9419                 emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
9420                 
9421                 if (AOP_TYPE(right) == AOP_LIT) {
9422                         unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
9423                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9424                         if(lit&0xff) {
9425                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9426                                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9427                         } else {
9428                                 emitpcode(POC_CLRF, popGet(AOP(result), offset));
9429                         }
9430                 } else {
9431                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9432                         emitpcode(POC_MOVFW, popGet(AOP(right), offset));
9433                         emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9434                 }
9435                 
9436                 offset++;
9437         }
9438         
9439         freeAsmop(right,NULL,ic,TRUE);
9440         freeAsmop(result,NULL,ic,TRUE);
9441 }
9442
9443 /*-----------------------------------------------------------------*/
9444 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9445 /*-----------------------------------------------------------------*/
9446 static void genNearPointerSet (operand *right,
9447                                                            operand *result, 
9448                                                            iCode *ic)
9449 {
9450         asmop *aop = NULL;
9451         sym_link *ptype = operandType(result);
9452         sym_link *retype = getSpec(operandType(right));
9453         sym_link *letype = getSpec(ptype);
9454         int direct = 0;
9455         
9456         
9457         FENTRY;
9458         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9459         aopOp(result,ic,FALSE);
9460         
9461 #if 1
9462         /* if the result is rematerializable &
9463         in data space & not a bit variable */
9464         //if (AOP_TYPE(result) == AOP_IMMD &&
9465         if (AOP_TYPE(result) == AOP_PCODE &&
9466                 PIC_IS_DATA_PTR(ptype) &&
9467                 !IS_BITVAR (retype) &&
9468                 !IS_BITVAR (letype)) {
9469                 genDataPointerSet (right,result,ic);
9470                 freeAsmop(result,NULL,ic,TRUE);
9471                 return;
9472         }
9473 #endif
9474
9475         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9476         aopOp(right,ic,FALSE);
9477         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9478         
9479         /* Check if can access directly instead of via a pointer */
9480         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9481                 direct = 1;
9482         }
9483         
9484         if (IS_BITFIELD (letype))
9485         {
9486           genPackBits (letype, result, right, direct?-1:POINTER);
9487           return;
9488         }
9489         
9490         /* If the pointer value is not in a the FSR then need to put it in */
9491         /* Must set/reset IRP bit for use with FSR. */
9492         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9493         if (!direct)
9494                 setup_fsr (result);
9495
9496         {
9497                 /* we have can just get the values */
9498                 int size = AOP_SIZE(right);
9499                 int offset = 0 ;    
9500                 
9501                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9502                 while (size--) {
9503                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9504                         if (*l == '@' ) {
9505                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9506                         } else {
9507                                 if (AOP_TYPE(right) == AOP_LIT) {
9508                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9509                                 } else {
9510                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9511                                 }
9512                                 if (direct)
9513                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9514                                 else
9515                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9516                         }
9517                         if (size && !direct)
9518                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9519                         offset++;
9520                 }
9521         }
9522         
9523         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9524         /* now some housekeeping stuff */
9525         if (aop) {
9526                 /* we had to allocate for this iCode */
9527                 freeAsmop(NULL,aop,ic,TRUE);
9528         } else { 
9529                 /* we did not allocate which means left
9530                 already in a pointer register, then
9531                 if size > 0 && this could be used again
9532                 we have to point it back to where it 
9533                 belongs */
9534                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9535                 if (AOP_SIZE(right) > 1 &&
9536                         !OP_SYMBOL(result)->remat &&
9537                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9538                         ic->depth )) {
9539                         int size = AOP_SIZE(right) - 1;
9540                         while (size--)
9541                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9542                 }
9543         }
9544         
9545         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9546         /* done */
9547
9548         freeAsmop(right,NULL,ic,TRUE);
9549         freeAsmop(result,NULL,ic,TRUE);
9550 }
9551
9552 #if 0
9553 /*-----------------------------------------------------------------*/
9554 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9555 /*-----------------------------------------------------------------*/
9556 static void genPagedPointerSet (operand *right,
9557                                                                 operand *result, 
9558                                                                 iCode *ic)
9559 {
9560         asmop *aop = NULL;
9561         regs *preg = NULL ;
9562         char *rname , *l;
9563         sym_link *retype;
9564         
9565         FENTRY;
9566         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9567         
9568         retype= getSpec(operandType(right));
9569         
9570         aopOp(result,ic,FALSE);
9571         
9572         /* if the value is already in a pointer register
9573         then don't need anything more */
9574         if (!AOP_INPREG(AOP(result))) {
9575                 /* otherwise get a free pointer register */
9576                 aop = newAsmop(0);
9577                 preg = getFreePtr(ic,&aop,FALSE);
9578                 pic14_emitcode("mov","%s,%s",
9579                         preg->name,
9580                         aopGet(AOP(result),0,FALSE,TRUE));
9581                 rname = preg->name ;
9582         } else
9583                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9584         
9585         freeAsmop(result,NULL,ic,TRUE);
9586         aopOp (right,ic,FALSE);
9587         
9588         /* if bitfield then unpack the bits */
9589         if (IS_BITFIELD(retype)) 
9590                 genPackBits (retype,result,right,rname,PPOINTER);
9591         else {
9592                 /* we have can just get the values */
9593                 int size = AOP_SIZE(right);
9594                 int offset = 0 ;  
9595                 
9596                 while (size--) {
9597                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9598                         
9599                         MOVA(l);
9600                         pic14_emitcode("movx","@%s,a",rname);
9601                         
9602                         if (size)
9603                                 pic14_emitcode("inc","%s",rname);
9604                         
9605                         offset++;
9606                 }
9607         }
9608         
9609         /* now some housekeeping stuff */
9610         if (aop) {
9611                 /* we had to allocate for this iCode */
9612                 freeAsmop(NULL,aop,ic,TRUE);
9613         } else { 
9614         /* we did not allocate which means left
9615         already in a pointer register, then
9616         if size > 0 && this could be used again
9617         we have to point it back to where it 
9618                 belongs */
9619                 if (AOP_SIZE(right) > 1 &&
9620                         !OP_SYMBOL(result)->remat &&
9621                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9622                         ic->depth )) {
9623                         int size = AOP_SIZE(right) - 1;
9624                         while (size--)
9625                                 pic14_emitcode("dec","%s",rname);
9626                 }
9627         }
9628         
9629         /* done */
9630         freeAsmop(right,NULL,ic,TRUE);
9631         
9632         
9633 }
9634
9635 /*-----------------------------------------------------------------*/
9636 /* genFarPointerSet - set value from far space                     */
9637 /*-----------------------------------------------------------------*/
9638 static void genFarPointerSet (operand *right,
9639                                                           operand *result, iCode *ic)
9640 {
9641         int size, offset ;
9642         sym_link *retype = getSpec(operandType(right));
9643         
9644         FENTRY;
9645         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9646         aopOp(result,ic,FALSE);
9647         
9648         /* if the operand is already in dptr 
9649         then we do nothing else we move the value to dptr */
9650         if (AOP_TYPE(result) != AOP_STR) {
9651                 /* if this is remateriazable */
9652                 if (AOP_TYPE(result) == AOP_IMMD)
9653                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9654                 else { /* we need to get it byte by byte */
9655                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9656                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9657                         if (options.model == MODEL_FLAT24)
9658                         {
9659                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9660                         }
9661                 }
9662         }
9663         /* so dptr know contains the address */
9664         freeAsmop(result,NULL,ic,TRUE);
9665         aopOp(right,ic,FALSE);
9666         
9667         /* if bit then unpack */
9668         if (IS_BITFIELD(retype)) 
9669                 genPackBits(retype,result,right,"dptr",FPOINTER);
9670         else {
9671                 size = AOP_SIZE(right);
9672                 offset = 0 ;
9673                 
9674                 while (size--) {
9675                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9676                         MOVA(l);
9677                         pic14_emitcode("movx","@dptr,a");
9678                         if (size)
9679                                 pic14_emitcode("inc","dptr");
9680                 }
9681         }
9682         
9683         freeAsmop(right,NULL,ic,TRUE);
9684 }
9685 #endif
9686
9687 /*-----------------------------------------------------------------*/
9688 /* genGenPointerSet - set value from generic pointer space         */
9689 /*-----------------------------------------------------------------*/
9690 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9691 {
9692         sym_link *retype = getSpec(operandType(result));
9693         
9694         FENTRY;
9695         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9696         aopOp(right,ic,FALSE);
9697         aopOp(result,ic,FALSE);
9698
9699         
9700         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9701
9702         if (IS_BITFIELD(retype))
9703         {
9704           genPackBits (retype, result, right, GPOINTER);
9705           return;
9706         }
9707
9708         {
9709           /* emit call to __gptrput */
9710           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9711           int size = AOP_SIZE(right);
9712           int idx = 0;
9713
9714           assert (size == getSize(OP_SYM_ETYPE(result)));
9715           assert (size > 0 && size <= 4);
9716
9717           /* pass arguments */
9718           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9719           {
9720             int off = size;
9721             idx = 2;
9722             while (off--)
9723             {
9724               mov2w_op (right, off);
9725               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9726             }
9727             idx = 0;
9728           }
9729           /* - address */
9730           assert (AOP_SIZE(result) == 3);
9731           mov2w(AOP(result), 0);
9732           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9733           mov2w(AOP(result), 1);
9734           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9735           mov2w(AOP(result), 2);
9736           call_libraryfunc (func[size]);
9737         }
9738         
9739         freeAsmop(right,NULL,ic,TRUE);
9740         freeAsmop(result,NULL,ic,TRUE);
9741 }
9742
9743 /*-----------------------------------------------------------------*/
9744 /* genPointerSet - stores the value into a pointer location        */
9745 /*-----------------------------------------------------------------*/
9746 static void genPointerSet (iCode *ic)
9747 {    
9748         operand *right, *result ;
9749         sym_link *type, *etype;
9750         int p_type;
9751         
9752         FENTRY;
9753         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9754         
9755         right = IC_RIGHT(ic);
9756         result = IC_RESULT(ic) ;
9757         
9758         /* depending on the type of pointer we need to
9759         move it to the correct pointer register */
9760         type = operandType(result);
9761         etype = getSpec(type);
9762         /* if left is of type of pointer then it is simple */
9763         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9764                 p_type = DCL_TYPE(type);
9765         }
9766         else {
9767                 /* we have to go by the storage class */
9768                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9769                 
9770                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9771                 /*      p_type = CPOINTER ;  */
9772                 /*  } */
9773                 /*  else */
9774                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9775                 /*    p_type = FPOINTER ; */
9776                 /*      else */
9777                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9778                 /*        p_type = PPOINTER ; */
9779                 /*    else */
9780                 /*        if (SPEC_OCLS(etype) == idata ) */
9781                 /*      p_type = IPOINTER ; */
9782                 /*        else */
9783                 /*      p_type = POINTER ; */
9784         }
9785         
9786         /* now that we have the pointer type we assign
9787         the pointer values */
9788         switch (p_type) {
9789                 
9790         case POINTER:
9791         case FPOINTER:
9792         //case IPOINTER:
9793                 genNearPointerSet (right,result,ic);
9794                 break;
9795 /*
9796         case PPOINTER:
9797                 genPagedPointerSet (right,result,ic);
9798                 break;
9799                 
9800         case FPOINTER:
9801                 genFarPointerSet (right,result,ic);
9802                 break;
9803 */
9804         case GPOINTER:
9805                 genGenPointerSet (right,result,ic);
9806                 break;
9807                 
9808         default:
9809                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9810                         "genPointerSet: illegal pointer type");
9811         }
9812 }
9813
9814 /*-----------------------------------------------------------------*/
9815 /* genIfx - generate code for Ifx statement                        */
9816 /*-----------------------------------------------------------------*/
9817 static void genIfx (iCode *ic, iCode *popIc)
9818 {
9819         operand *cond = IC_COND(ic);
9820         int isbit =0;
9821         
9822         FENTRY;
9823         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9824         
9825         aopOp(cond,ic,FALSE);
9826         
9827         /* get the value into acc */
9828         if (AOP_TYPE(cond) != AOP_CRY)
9829                 pic14_toBoolean(cond);
9830         else
9831                 isbit = 1;
9832         
9833         /* if there was something to be popped then do it */
9834         if (popIc)
9835                 genIpop(popIc);
9836         
9837         if (isbit)
9838         {
9839                 /* This assumes that CARRY is set iff cond is true */
9840                 if (IC_TRUE(ic))
9841                 {
9842                         assert (!IC_FALSE(ic));
9843                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9844                         //emitSKPNC;
9845                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9846                 } else {
9847                         assert (IC_FALSE(ic));
9848                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9849                         //emitSKPC;
9850                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9851                 }
9852                 if (0)
9853                 {
9854                         static int hasWarned = 0;
9855                         if (!hasWarned)
9856                         {
9857                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9858                                 hasWarned = 1;
9859                         }
9860                 }
9861         }
9862         else
9863         {
9864                 /* now Z is set iff !cond */
9865                 if (IC_TRUE(ic))
9866                 {
9867                         assert (!IC_FALSE(ic));
9868                         emitSKPZ;
9869                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9870                 } else {
9871                         emitSKPNZ;
9872                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9873                 }
9874         }
9875         
9876         ic->generated = 1;
9877         
9878         /* the result is now in the accumulator */
9879         freeAsmop(cond,NULL,ic,TRUE);
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         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9925                 /* strip tag */
9926                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9927         }
9928         offset = 0;
9929         
9930         while (size--) {
9931                 /* fixing bug #863624, reported from (errolv) */
9932                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9933                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9934                 
9935 #if 0
9936                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9937                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9938 #endif
9939                 offset++;
9940         }
9941
9942         if (IS_GENPTR(OP_SYM_TYPE(result)))
9943         {
9944                 /* provide correct tag */
9945                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9946                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9947                 movwf (AOP(result), 2);
9948         }
9949         
9950         freeAsmop(left,NULL,ic,FALSE);
9951         freeAsmop(result,NULL,ic,TRUE);
9952         
9953 }
9954
9955 #if 0
9956 /*-----------------------------------------------------------------*/
9957 /* genFarFarAssign - assignment when both are in far space         */
9958 /*-----------------------------------------------------------------*/
9959 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9960 {
9961         int size = AOP_SIZE(right);
9962         int offset = 0;
9963         char *l ;
9964         /* first push the right side on to the stack */
9965         while (size--) {
9966                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9967                 MOVA(l);
9968                 pic14_emitcode ("push","acc");
9969         }
9970         
9971         freeAsmop(right,NULL,ic,FALSE);
9972         /* now assign DPTR to result */
9973         aopOp(result,ic,FALSE);
9974         size = AOP_SIZE(result);
9975         while (size--) {
9976                 pic14_emitcode ("pop","acc");
9977                 aopPut(AOP(result),"a",--offset);
9978         }
9979         freeAsmop(result,NULL,ic,FALSE);
9980         
9981 }
9982 #endif
9983
9984 /*-----------------------------------------------------------------*/
9985 /* genAssign - generate code for assignment                        */
9986 /*-----------------------------------------------------------------*/
9987 static void genAssign (iCode *ic)
9988 {
9989         operand *result, *right;
9990         int size, offset,know_W;
9991         unsigned long lit = 0L;
9992         
9993         result = IC_RESULT(ic);
9994         right  = IC_RIGHT(ic) ;
9995         
9996         FENTRY;
9997         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9998         
9999         /* if they are the same */
10000         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10001                 return ;
10002         
10003         aopOp(right,ic,FALSE);
10004         aopOp(result,ic,TRUE);
10005         
10006         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10007         
10008         /* if they are the same registers */
10009         if (pic14_sameRegs(AOP(right),AOP(result)))
10010                 goto release;
10011
10012         /* special case: assign from __code */
10013         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10014                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10015                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10016                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10017                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10018         {
10019           emitpComment ("genAssign from CODESPACE");
10020           genConstPointerGet (right, result, ic);
10021           goto release;
10022         }
10023         
10024         /* just for symmetry reasons... */
10025         if (!IS_ITEMP(result)
10026                 && IS_SYMOP (result)
10027                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10028         {
10029           assert ( !"cannot write to CODESPACE" );
10030         }
10031
10032         /* if the result is a bit */
10033         if (AOP_TYPE(result) == AOP_CRY) {
10034                 
10035         /* if the right size is a literal then
10036                 we know what the value is */
10037                 if (AOP_TYPE(right) == AOP_LIT) {
10038                         
10039                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10040                                 popGet(AOP(result),0));
10041                         
10042                         if (((int) operandLitValue(right))) 
10043                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10044                                 AOP(result)->aopu.aop_dir,
10045                                 AOP(result)->aopu.aop_dir);
10046                         else
10047                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10048                                 AOP(result)->aopu.aop_dir,
10049                                 AOP(result)->aopu.aop_dir);
10050                         goto release;
10051                 }
10052                 
10053                 /* the right is also a bit variable */
10054                 if (AOP_TYPE(right) == AOP_CRY) {
10055                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10056                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10057                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10058                         
10059                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10060                                 AOP(result)->aopu.aop_dir,
10061                                 AOP(result)->aopu.aop_dir);
10062                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10063                                 AOP(right)->aopu.aop_dir,
10064                                 AOP(right)->aopu.aop_dir);
10065                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10066                                 AOP(result)->aopu.aop_dir,
10067                                 AOP(result)->aopu.aop_dir);
10068                         goto release ;
10069                 }
10070                 
10071                 /* we need to or */
10072                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10073                 pic14_toBoolean(right);
10074                 emitSKPZ;
10075                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10076                 //aopPut(AOP(result),"a",0);
10077                 goto release ;
10078         }
10079         
10080         /* bit variables done */
10081         /* general case */
10082         size = AOP_SIZE(result);
10083         offset = 0 ;
10084         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10085                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10086                 if(aopIdx(AOP(result),0) == 4) {
10087                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10088                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10089                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10090                         goto release;
10091                 } else
10092                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10093         }
10094         
10095         know_W=-1;
10096         while (size--) {
10097         
10098                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10099                 if(AOP_TYPE(right) == AOP_LIT) {
10100                         lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
10101                         if(lit&0xff) {
10102                                 if(know_W != (int)(lit&0xff))
10103                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10104                                 know_W = lit&0xff;
10105                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10106                         } else
10107                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10108                         
10109                 } else if (AOP_TYPE(right) == AOP_CRY) {
10110                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10111                         if(offset == 0) {
10112                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10113                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10114                         }
10115                 } else {
10116                         mov2w_op (right, offset);
10117                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10118                 }
10119                 
10120                 offset++;
10121         }
10122         
10123         
10124 release:
10125         freeAsmop (right,NULL,ic,FALSE);
10126         freeAsmop (result,NULL,ic,TRUE);
10127 }   
10128
10129 /*-----------------------------------------------------------------*/
10130 /* genJumpTab - genrates code for jump table                       */
10131 /*-----------------------------------------------------------------*/
10132 static void genJumpTab (iCode *ic)
10133 {
10134         symbol *jtab;
10135         char *l;
10136         
10137         FENTRY;
10138         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10139         
10140         aopOp(IC_JTCOND(ic),ic,FALSE);
10141         /* get the condition into accumulator */
10142         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10143         MOVA(l);
10144         /* multiply by three */
10145         pic14_emitcode("add","a,acc");
10146         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10147         
10148         jtab = newiTempLabel(NULL);
10149         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10150         pic14_emitcode("jmp","@a+dptr");
10151         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10152         
10153         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10154         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10155         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10156         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10157         emitSKPNC;
10158         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10159         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10160         emitpLabel(jtab->key);
10161         
10162         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10163         
10164         /* now generate the jump labels */
10165         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10166         jtab = setNextItem(IC_JTLABELS(ic))) {
10167                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10168                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10169                 
10170         }
10171         
10172 }
10173
10174 /*-----------------------------------------------------------------*/
10175 /* genMixedOperation - gen code for operators between mixed types  */
10176 /*-----------------------------------------------------------------*/
10177 /*
10178 TSD - Written for the PIC port - but this unfortunately is buggy.
10179 This routine is good in that it is able to efficiently promote 
10180 types to different (larger) sizes. Unfortunately, the temporary
10181 variables that are optimized out by this routine are sometimes
10182 used in other places. So until I know how to really parse the 
10183 iCode tree, I'm going to not be using this routine :(.
10184 */
10185 static int genMixedOperation (iCode *ic)
10186 {
10187         FENTRY;
10188 #if 0
10189         operand *result = IC_RESULT(ic);
10190         sym_link *ctype = operandType(IC_LEFT(ic));
10191         operand *right = IC_RIGHT(ic);
10192         int ret = 0;
10193         int big,small;
10194         int offset;
10195         
10196         iCode *nextic;
10197         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10198         
10199         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10200         
10201         nextic = ic->next;
10202         if(!nextic)
10203                 return 0;
10204         
10205         nextright = IC_RIGHT(nextic);
10206         nextleft  = IC_LEFT(nextic);
10207         nextresult = IC_RESULT(nextic);
10208         
10209         aopOp(right,ic,FALSE);
10210         aopOp(result,ic,FALSE);
10211         aopOp(nextright,  nextic, FALSE);
10212         aopOp(nextleft,   nextic, FALSE);
10213         aopOp(nextresult, nextic, FALSE);
10214         
10215         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10216                 
10217                 operand *t = right;
10218                 right = nextright;
10219                 nextright = t; 
10220                 
10221                 pic14_emitcode(";remove right +","");
10222                 
10223         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10224         /*
10225         operand *t = right;
10226         right = nextleft;
10227         nextleft = t; 
10228                 */
10229                 pic14_emitcode(";remove left +","");
10230         } else
10231                 return 0;
10232         
10233         big = AOP_SIZE(nextleft);
10234         small = AOP_SIZE(nextright);
10235         
10236         switch(nextic->op) {
10237                 
10238         case '+':
10239                 pic14_emitcode(";optimize a +","");
10240                 /* if unsigned or not an integral type */
10241                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10242                         pic14_emitcode(";add a bit to something","");
10243                 } else {
10244                         
10245                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10246                         
10247                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10248                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10249                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10250                         } else
10251                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10252                         
10253                         offset = 0;
10254                         while(--big) {
10255                                 
10256                                 offset++;
10257                                 
10258                                 if(--small) {
10259                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10260                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10261                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10262                                         }
10263                                         
10264                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10265                                         emitSKPNC;
10266                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10267                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10268                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10269                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10270                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10271                                         
10272                                 } else {
10273                                         pic14_emitcode("rlf","known_zero,w");
10274                                         
10275                                         /*
10276                                         if right is signed
10277                                         btfsc  right,7
10278                                         addlw ff
10279                                         */
10280                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10281                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10282                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10283                                         } else {
10284                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10285                                         }
10286                                 }
10287                         }
10288                         ret = 1;
10289                 }
10290         }
10291         ret = 1;
10292         
10293 release:
10294         freeAsmop(right,NULL,ic,TRUE);
10295         freeAsmop(result,NULL,ic,TRUE);
10296         freeAsmop(nextright,NULL,ic,TRUE);
10297         freeAsmop(nextleft,NULL,ic,TRUE);
10298         if(ret)
10299                 nextic->generated = 1;
10300         
10301         return ret;
10302 #else
10303         return 0;
10304 #endif
10305 }
10306 /*-----------------------------------------------------------------*/
10307 /* genCast - gen code for casting                                  */
10308 /*-----------------------------------------------------------------*/
10309 static void genCast (iCode *ic)
10310 {
10311         operand *result = IC_RESULT(ic);
10312         sym_link *restype = operandType(result);
10313         sym_link *rtype = operandType(IC_RIGHT(ic));
10314         operand *right = IC_RIGHT(ic);
10315         int size, offset ;
10316         
10317         FENTRY;
10318         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10319         /* if they are equivalent then do nothing */
10320         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10321                 return ;
10322         
10323         aopOp(right,ic,FALSE) ;
10324         aopOp(result,ic,FALSE);
10325         
10326         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10327         
10328         /* if the result is a bit */
10329         if (AOP_TYPE(result) == AOP_CRY) {
10330                 assert(!"assigning to bit variables is not supported");
10331         }
10332         
10333         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10334                 int offset = 1;
10335                 size = AOP_SIZE(result);
10336                 
10337                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10338                 
10339                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10340                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10341                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10342                 
10343                 while (size--)
10344                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10345                 
10346                 goto release;
10347         }
10348         
10349         if (IS_PTR(restype))
10350         {
10351           operand *result = IC_RESULT(ic);
10352           //operand *left = IC_LEFT(ic);
10353           operand *right = IC_RIGHT(ic);
10354           int tag = 0xff;
10355           
10356           /* copy common part */
10357           int max, size = AOP_SIZE(result);
10358           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10359           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10360
10361           /* warn if we discard generic opinter tag */
10362           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10363           {
10364             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10365           } // if
10366
10367           max = size;
10368           while (size--)
10369           {
10370             mov2w_op (right, size);
10371             movwf (AOP(result), size);
10372           } // while
10373
10374           /* upcast into generic pointer type? */
10375           if (IS_GENPTR(restype)
10376                 && (size < AOP_SIZE(result))
10377                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10378           {
10379             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10380             if (IS_PTR(rtype))
10381             {
10382               switch (DCL_TYPE(rtype))
10383               {
10384               case POINTER:     /* __data */
10385               case FPOINTER:    /* __data */
10386                 assert (AOP_SIZE(right) == 2);
10387                 tag = GPTRTAG_DATA;
10388                 break;
10389
10390               case CPOINTER:    /* __code */
10391                 assert (AOP_SIZE(right) == 2);
10392                 tag = GPTRTAG_CODE;
10393                 break;
10394                 
10395               case GPOINTER:    /* unknown destination, __data or __code */
10396                 /* assume __data space (address of immediate) */
10397                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10398                 if (AOP(right)->code)
10399                   tag = GPTRTAG_CODE;
10400                 else
10401                   tag = GPTRTAG_DATA;
10402                 break;
10403                 
10404               default:
10405                 assert (!"unhandled pointer type");
10406               } // switch
10407             } else {
10408               /* convert other values into pointers to __data space */
10409               tag = GPTRTAG_DATA;
10410             }
10411
10412             assert (AOP_SIZE(result) == 3);
10413             if (tag == 0) {
10414               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10415             } else {
10416               emitpcode(POC_MOVLW, popGetLit(tag));
10417               movwf(AOP(result), 2);
10418             }
10419           } else {
10420             addSign(result, max, 0);
10421           } // if
10422           goto release;
10423         }
10424         
10425         /* if they are the same size : or less */
10426         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10427                 
10428                 /* if they are in the same place */
10429                 if (pic14_sameRegs(AOP(right),AOP(result)))
10430                         goto release;
10431                 
10432                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10433                 if (IS_PTR_CONST(rtype))
10434                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10435                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10436                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10437                 
10438                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10439                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10440                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10441                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10442                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10443                         if(AOP_SIZE(result) <2)
10444                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10445                         
10446                 } else {
10447                         
10448                         /* if they in different places then copy */
10449                         size = AOP_SIZE(result);
10450                         offset = 0 ;
10451                         while (size--) {
10452                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10453                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10454                                 
10455                                 //aopPut(AOP(result),
10456                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10457                                 // offset);
10458                                 
10459                                 offset++;
10460                         }
10461                 }
10462                 goto release;
10463         }
10464         
10465         /* so we now know that the size of destination is greater
10466         than the size of the source.
10467         Now, if the next iCode is an operator then we might be
10468         able to optimize the operation without performing a cast.
10469         */
10470         if(0 && genMixedOperation(ic)) {
10471                 /* XXX: cannot optimize: must copy regs! */
10472                 goto release;
10473         }
10474         
10475         /* we move to result for the size of source */
10476         size = AOP_SIZE(right);
10477         offset = 0 ;
10478         while (size--) {
10479                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10480                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10481                 offset++;
10482         }
10483
10484         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10485
10486 release:
10487         freeAsmop(right,NULL,ic,TRUE);
10488         freeAsmop(result,NULL,ic,TRUE);
10489         
10490 }
10491
10492 /*-----------------------------------------------------------------*/
10493 /* genDjnz - generate decrement & jump if not zero instrucion      */
10494 /*-----------------------------------------------------------------*/
10495 static int genDjnz (iCode *ic, iCode *ifx)
10496 {
10497         symbol *lbl, *lbl1;
10498         FENTRY;
10499         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10500         
10501         if (!ifx)
10502                 return 0;
10503         
10504                 /* if the if condition has a false label
10505         then we cannot save */
10506         if (IC_FALSE(ifx))
10507                 return 0;
10508         
10509                 /* if the minus is not of the form 
10510         a = a - 1 */
10511         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10512                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10513                 return 0;
10514         
10515         if (operandLitValue(IC_RIGHT(ic)) != 1)
10516                 return 0;
10517         
10518                 /* if the size of this greater than one then no
10519         saving */
10520         if (getSize(operandType(IC_RESULT(ic))) > 1)
10521                 return 0;
10522         
10523         /* otherwise we can save BIG */
10524         lbl = newiTempLabel(NULL);
10525         lbl1= newiTempLabel(NULL);
10526         
10527         aopOp(IC_RESULT(ic),ic,FALSE);
10528         
10529         if (IS_AOP_PREG(IC_RESULT(ic))) {
10530                 pic14_emitcode("dec","%s",
10531                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10532                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10533                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10534         } else {  
10535                 
10536                 
10537                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10538                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10539                 
10540                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10541                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10542                 
10543         }
10544         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10545         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10546         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10547         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10548         
10549         
10550         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10551         ifx->generated = 1;
10552         return 1;
10553 }
10554
10555 /*-----------------------------------------------------------------*/
10556 /* genReceive - generate code for a receive iCode                  */
10557 /*-----------------------------------------------------------------*/
10558 static void genReceive (iCode *ic)
10559 {
10560         FENTRY;
10561         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10562         
10563         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10564                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10565                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10566                 
10567                 int size = getSize(operandType(IC_RESULT(ic)));
10568                 int offset =  fReturnSizePic - size;
10569                 while (size--) {
10570                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10571                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10572                         offset++;
10573                 }
10574                 aopOp(IC_RESULT(ic),ic,FALSE);
10575                 size = AOP_SIZE(IC_RESULT(ic));
10576                 offset = 0;
10577                 while (size--) {
10578                         pic14_emitcode ("pop","acc");
10579                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10580                 }
10581                 
10582         } else {
10583                 _G.accInUse++;
10584                 aopOp(IC_RESULT(ic),ic,FALSE);
10585                 _G.accInUse--;
10586                 GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
10587                 assignResultValue(IC_RESULT(ic));
10588         }
10589         
10590         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10591 }
10592
10593 /*-----------------------------------------------------------------*/
10594 /* genDummyRead - generate code for dummy read of volatiles        */
10595 /*-----------------------------------------------------------------*/
10596 static void
10597 genDummyRead (iCode * ic)
10598 {
10599         FENTRY;
10600         pic14_emitcode ("; genDummyRead","");
10601         pic14_emitcode ("; not implemented","");
10602         
10603         ic = ic;
10604 }
10605
10606 /*-----------------------------------------------------------------*/
10607 /* genpic14Code - generate code for pic14 based controllers        */
10608 /*-----------------------------------------------------------------*/
10609 /*
10610 * At this point, ralloc.c has gone through the iCode and attempted
10611 * to optimize in a way suitable for a PIC. Now we've got to generate
10612 * PIC instructions that correspond to the iCode.
10613 *
10614 * Once the instructions are generated, we'll pass through both the
10615 * peep hole optimizer and the pCode optimizer.
10616 *-----------------------------------------------------------------*/
10617
10618 void genpic14Code (iCode *lic)
10619 {
10620         iCode *ic;
10621         int cln = 0;
10622         const char *cline;
10623         
10624         FENTRY;
10625         lineHead = lineCurr = NULL;
10626         
10627         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10628         addpBlock(pb);
10629         
10630         /* if debug information required */
10631         if (options.debug && currFunc) { 
10632                 if (currFunc) {
10633                         debugFile->writeFunction (currFunc, lic);
10634                 }
10635         }
10636         
10637         
10638         for (ic = lic ; ic ; ic = ic->next ) {
10639                 
10640                 //DEBUGpic14_emitcode(";ic","");
10641                 //fprintf (stderr, "in ic loop\n");
10642                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10643                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10644                 
10645                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10646                   cln = ic->lineno;
10647                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10648                   cline = printCLine (ic->filename, ic->lineno);
10649                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10650                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10651                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10652                 }
10653                 
10654                 if (options.iCodeInAsm) {
10655                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10656                 }
10657                 /* if the result is marked as
10658                 spilt and rematerializable or code for
10659                 this has already been generated then
10660                 do nothing */
10661                 if (resultRemat(ic) || ic->generated ) 
10662                         continue ;
10663                 
10664                 /* depending on the operation */
10665                 switch (ic->op) {
10666                 case '!' :
10667                         genNot(ic);
10668                         break;
10669                         
10670                 case '~' :
10671                         genCpl(ic);
10672                         break;
10673                         
10674                 case UNARYMINUS:
10675                         genUminus (ic);
10676                         break;
10677                         
10678                 case IPUSH:
10679                         genIpush (ic);
10680                         break;
10681                         
10682                 case IPOP:
10683                         /* IPOP happens only when trying to restore a 
10684                         spilt live range, if there is an ifx statement
10685                         following this pop then the if statement might
10686                         be using some of the registers being popped which
10687                         would destory the contents of the register so
10688                         we need to check for this condition and handle it */
10689                         if (ic->next            && 
10690                                 ic->next->op == IFX &&
10691                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10692                                 genIfx (ic->next,ic);
10693                         else
10694                                 genIpop (ic);
10695                         break; 
10696                         
10697                 case CALL:
10698                         genCall (ic);
10699                         break;
10700                         
10701                 case PCALL:
10702                         genPcall (ic);
10703                         break;
10704                         
10705                 case FUNCTION:
10706                         genFunction (ic);
10707                         break;
10708                         
10709                 case ENDFUNCTION:
10710                         genEndFunction (ic);
10711                         break;
10712                         
10713                 case RETURN:
10714                         genRet (ic);
10715                         break;
10716                         
10717                 case LABEL:
10718                         genLabel (ic);
10719                         break;
10720                         
10721                 case GOTO:
10722                         genGoto (ic);
10723                         break;
10724                         
10725                 case '+' :
10726                         genPlus (ic) ;
10727                         break;
10728                         
10729                 case '-' :
10730                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10731                                 genMinus (ic);
10732                         break;
10733                         
10734                 case '*' :
10735                         genMult (ic);
10736                         break;
10737                         
10738                 case '/' :
10739                         genDiv (ic) ;
10740                         break;
10741                         
10742                 case '%' :
10743                         genMod (ic);
10744                         break;
10745                         
10746                 case '>' :
10747                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10748                         break;
10749                         
10750                 case '<' :
10751                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10752                         break;
10753                         
10754                 case LE_OP:
10755                 case GE_OP:
10756                 case NE_OP:
10757                         
10758                         /* note these two are xlated by algebraic equivalence
10759                         during parsing SDCC.y */
10760                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10761                                 "got '>=' or '<=' shouldn't have come here");
10762                         break;  
10763                         
10764                 case EQ_OP:
10765                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10766                         break;      
10767                         
10768                 case AND_OP:
10769                         genAndOp (ic);
10770                         break;
10771                         
10772                 case OR_OP:
10773                         genOrOp (ic);
10774                         break;
10775                         
10776                 case '^' :
10777                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10778                         break;
10779                         
10780                 case '|' :
10781                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10782                         break;
10783                         
10784                 case BITWISEAND:
10785                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10786                         break;
10787                         
10788                 case INLINEASM:
10789                         genInline (ic);
10790                         break;
10791                         
10792                 case RRC:
10793                         genRRC (ic);
10794                         break;
10795                         
10796                 case RLC:
10797                         genRLC (ic);
10798                         break;
10799                         
10800                 case GETHBIT:
10801                         genGetHbit (ic);
10802                         break;
10803                         
10804                 case LEFT_OP:
10805                         genLeftShift (ic);
10806                         break;
10807                         
10808                 case RIGHT_OP:
10809                         genRightShift (ic);
10810                         break;
10811                         
10812                 case GET_VALUE_AT_ADDRESS:
10813                         genPointerGet(ic);
10814                         break;
10815                         
10816                 case '=' :
10817                         if (POINTER_SET(ic))
10818                                 genPointerSet(ic);
10819                         else
10820                                 genAssign(ic);
10821                         break;
10822                         
10823                 case IFX:
10824                         genIfx (ic,NULL);
10825                         break;
10826                         
10827                 case ADDRESS_OF:
10828                         genAddrOf (ic);
10829                         break;
10830                         
10831                 case JUMPTABLE:
10832                         genJumpTab (ic);
10833                         break;
10834                         
10835                 case CAST:
10836                         genCast (ic);
10837                         break;
10838                         
10839                 case RECEIVE:
10840                         genReceive(ic);
10841                         break;
10842                         
10843                 case SEND:
10844                         addSet(&_G.sendSet,ic);
10845                         break;
10846                         
10847                 case DUMMY_READ_VOLATILE:
10848                         genDummyRead (ic);
10849                         break;
10850                         
10851                 default :
10852                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10853                         ic = ic;
10854                         break;
10855                 }
10856         }
10857
10858         
10859         /* now we are ready to call the
10860         peep hole optimizer */
10861         if (!options.nopeep) {
10862                 peepHole (&lineHead);
10863         }
10864         /* now do the actual printing */
10865         printLine (lineHead,codeOutFile);
10866         
10867 #ifdef PCODE_DEBUG
10868         DFPRINTF((stderr,"printing pBlock\n\n"));
10869         printpBlock(stdout,pb);
10870 #endif
10871         
10872         return;
10873 }
10874
10875 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10876  * (meaning: representing its own address) or not (referencing its contents).
10877  * This can only be decided based on the operand's type. */
10878 int
10879 aop_isLitLike (asmop *aop)
10880 {
10881   assert (aop);
10882   if (aop->type == AOP_LIT) return 1;
10883 if (aop->type == AOP_IMMD) return 1;
10884   if ((aop->type == AOP_PCODE) &&
10885                 ((aop->aopu.pcop->type == PO_LITERAL)))
10886   {
10887     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10888      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10889     return 1;
10890   }
10891   return 0;
10892 }
10893
10894 int
10895 op_isLitLike (operand *op)
10896 {
10897   assert (op);
10898   if (aop_isLitLike (AOP(op))) return 1;
10899   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10900   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10901   return 0;
10902 }