* src/pic/gen.c (bitpatternFromVal): fixed for 64-bit machines
[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 <stdint.h>
38 #include "SDCCglobl.h"
39 #include "newalloc.h"
40
41 #include "common.h"
42 #include "SDCCpeeph.h"
43 #include "ralloc.h"
44 #include "pcode.h"
45 #include "gen.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
73 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
74 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
75 unsigned int pic14aopLiteral (value *val, int offset);
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                 DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
280 }
281
282 void emitpcodeNULLop(PIC_OPCODE poc)
283 {
284         
285         addpCode2pBlock(pb,newpCode(poc,NULL));
286         
287 }
288
289
290 /*-----------------------------------------------------------------*/
291 /* pic14_emitcode - writes the code into a file : for now it is simple    */
292 /*-----------------------------------------------------------------*/
293 void pic14_emitcode (char *inst,char *fmt, ...)
294 {
295         va_list ap;
296         char lb[INITIAL_INLINEASM];  
297         unsigned char *lbp = (unsigned char *)lb;
298         
299         va_start(ap,fmt);   
300         
301         if (inst && *inst) {
302                 if (fmt && *fmt)
303                         sprintf(lb,"%s\t",inst);
304                 else
305                         sprintf(lb,"%s",inst);
306                 vsprintf(lb+(strlen(lb)),fmt,ap);
307         }  else
308                 vsprintf(lb,fmt,ap);
309         
310         while (isspace(*lbp)) lbp++;
311         
312         if (lbp && *lbp) 
313                 lineCurr = (lineCurr ?
314                 connectLine(lineCurr,newLineNode(lb)) :
315         (lineHead = newLineNode(lb)));
316         lineCurr->isInline = _G.inLine;
317         lineCurr->isDebug  = _G.debugLine;
318         
319         if(debug_verbose)
320                 addpCode2pBlock(pb,newpCodeCharP(lb));
321         
322         va_end(ap);
323 }
324
325 /*-----------------------------------------------------------------*/
326 /* pic14_emitDebuggerSymbol - associate the current code location  */
327 /*       with a debugger symbol                                                                            */
328 /*-----------------------------------------------------------------*/
329 void
330 pic14_emitDebuggerSymbol (char * debugSym)
331 {
332         _G.debugLine = 1;
333         pic14_emitcode ("", ";%s ==.", debugSym);
334         _G.debugLine = 0;
335 }
336
337 #if 0
338 /*-----------------------------------------------------------------*/
339 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
340 /*-----------------------------------------------------------------*/
341 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
342 {
343         bool r0iu = FALSE , r1iu = FALSE;
344         bool r0ou = FALSE , r1ou = FALSE;
345         
346         /* the logic: if r0 & r1 used in the instruction
347         then we are in trouble otherwise */
348         
349         /* first check if r0 & r1 are used by this
350         instruction, in which case we are in trouble */
351         if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
352                 (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
353         {
354                 goto endOfWorld;          
355         }
356         
357         r0ou = bitVectBitValue(ic->rMask,R0_IDX);
358         r1ou = bitVectBitValue(ic->rMask,R1_IDX);
359         
360         /* if no usage of r0 then return it */
361         if (!r0iu && !r0ou) {
362                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
363                 (*aopp)->type = AOP_R0;
364                 
365                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
366         }
367         
368         /* if no usage of r1 then return it */
369         if (!r1iu && !r1ou) {
370                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
371                 (*aopp)->type = AOP_R1;
372                 
373                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R1_IDX);
374         }    
375         
376         /* now we know they both have usage */
377         /* if r0 not used in this instruction */
378         if (!r0iu) {
379                 /* push it if not already pushed */
380                 if (!_G.r0Pushed) {
381                         //pic14_emitcode ("push","%s",
382                         //                pic14_regWithIdx(R0_IDX)->dname);
383                         _G.r0Pushed++ ;
384                 }
385                 
386                 ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
387                 (*aopp)->type = AOP_R0;
388                 
389                 return (*aopp)->aopu.aop_ptr = pic14_regWithIdx(R0_IDX);
390         }
391         
392         /* if r1 not used then */
393         
394         if (!r1iu) {
395                 /* push it if not already pushed */
396                 if (!_G.r1Pushed) {
397                         //pic14_emitcode ("push","%s",
398                         //                pic14_regWithIdx(R1_IDX)->dname);
399                         _G.r1Pushed++ ;
400                 }
401                 
402                 ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
403                 (*aopp)->type = AOP_R1;
404                 return pic14_regWithIdx(R1_IDX);
405         }
406         
407 endOfWorld :
408         /* I said end of world but not quite end of world yet */
409         /* if this is a result then we can push it on the stack*/
410         if (result) {
411                 (*aopp)->type = AOP_STK;        
412                 return NULL;
413         }
414         
415         /* other wise this is true end of the world */
416         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
417                 "getFreePtr should never reach here");
418         exit(0);
419 }
420 #endif
421
422 /*-----------------------------------------------------------------*/
423 /* newAsmop - creates a new asmOp                                                                  */
424 /*-----------------------------------------------------------------*/
425 asmop *newAsmop (short type)
426 {
427         asmop *aop;
428         
429         aop = Safe_calloc(1,sizeof(asmop));
430         aop->type = type;
431         return aop;
432 }
433
434 static void genSetDPTR(int n)
435 {
436         if (!n)
437         {
438                 pic14_emitcode(";", "Select standard DPTR");
439                 pic14_emitcode("mov", "dps, #0x00");
440         }
441         else
442         {
443                 pic14_emitcode(";", "Select alternate DPTR");
444                 pic14_emitcode("mov", "dps, #0x01");
445         }
446 }
447
448 /*-----------------------------------------------------------------*/
449 /* resolveIfx - converts an iCode ifx into a form more useful for  */
450 /*                              generating code                                                                    */
451 /*-----------------------------------------------------------------*/
452 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
453 {
454         if(!resIfx) 
455                 return;
456         
457         //  DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
458         
459         resIfx->condition = 1;  /* assume that the ifx is true */
460         resIfx->generated = 0;  /* indicate that the ifx has not been used */
461         
462         if(!ifx) {
463                 resIfx->lbl = NULL; /* this is wrong: newiTempLabel(NULL);      / * oops, there is no ifx. so create a label */
464                                                                                         /*
465                                                                                         DEBUGpic14_emitcode("; ***","%s %d null ifx creating new label key =%d",
466                                                                                         __FUNCTION__,__LINE__,resIfx->lbl->key);
467                 */
468         } else {
469                 if(IC_TRUE(ifx)) {
470                         resIfx->lbl = IC_TRUE(ifx);
471                 } else {
472                         resIfx->lbl = IC_FALSE(ifx);
473                         resIfx->condition = 0;
474                 }
475                 /*
476                 if(IC_TRUE(ifx)) 
477                 DEBUGpic14_emitcode("; ***","ifx true is non-null");
478                 if(IC_FALSE(ifx)) 
479                 DEBUGpic14_emitcode("; ***","ifx false is non-null");
480                 */
481         }
482         
483         //  DEBUGpic14_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
484         
485 }
486 /*-----------------------------------------------------------------*/
487 /* pointerCode - returns the code for a pointer type                       */
488 /*-----------------------------------------------------------------*/
489 #if 0
490 static int pointerCode (sym_link *etype)
491 {
492         
493         return PTR_TYPE(SPEC_OCLS(etype));
494         
495 }
496 #endif
497
498 /*-----------------------------------------------------------------*/
499 /* aopForSym - for a true symbol                                                                   */
500 /*-----------------------------------------------------------------*/
501 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
502 {
503         asmop *aop;
504         memmap *space= SPEC_OCLS(sym->etype);
505         
506         DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
507         /* if already has one */
508         if (sym->aop)
509                 return sym->aop;
510         
511 #if 0
512         /* assign depending on the storage class */
513         /* if it is on the stack or indirectly addressable */
514         /* space we need to assign either r0 or r1 to it         */    
515         if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
516                 sym->aop = aop = newAsmop(0);
517                 aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
518                 aop->size = getSize(sym->type);
519                 
520                 /* now assign the address of the variable to 
521                 the pointer register */
522                 if (aop->type != AOP_STK) {
523                         
524                         if (sym->onStack) {
525                                 if ( _G.accInUse )
526                                         pic14_emitcode("push","acc");
527                                 
528                                 pic14_emitcode("mov","a,_bp");
529                                 pic14_emitcode("add","a,#0x%02x",
530                                         ((sym->stack < 0) ?
531                                         ((char)(sym->stack - _G.nRegsSaved )) :
532                                 ((char)sym->stack)) & 0xff);
533                                 pic14_emitcode("mov","%s,a",
534                                         aop->aopu.aop_ptr->name);
535                                 
536                                 if ( _G.accInUse )
537                                         pic14_emitcode("pop","acc");
538                         } else
539                                 pic14_emitcode("mov","%s,#%s",
540                                 aop->aopu.aop_ptr->name,
541                                 sym->rname);
542                         aop->paged = space->paged;
543                 } else
544                         aop->aopu.aop_stk = sym->stack;
545                 return aop;
546         }
547         
548         if (sym->onStack && options.stack10bit)
549         {
550                 /* It's on the 10 bit stack, which is located in
551                 * far data space.
552                 */
553                 
554                 //DEBUGpic14_emitcode(";","%d",__LINE__);
555                 
556                 if ( _G.accInUse )
557                         pic14_emitcode("push","acc");
558                 
559                 pic14_emitcode("mov","a,_bp");
560                 pic14_emitcode("add","a,#0x%02x",
561                         ((sym->stack < 0) ?
562                         ((char)(sym->stack - _G.nRegsSaved )) :
563                 ((char)sym->stack)) & 0xff);
564                 
565                 genSetDPTR(1);
566                 pic14_emitcode ("mov","dpx1,#0x40");
567                 pic14_emitcode ("mov","dph1,#0x00");
568                 pic14_emitcode ("mov","dpl1, a");
569                 genSetDPTR(0);
570                 
571                 if ( _G.accInUse )
572                         pic14_emitcode("pop","acc");
573                 
574                 sym->aop = aop = newAsmop(AOP_DPTR2);
575                 aop->size = getSize(sym->type); 
576                 return aop;
577         }
578 #endif
579
580         //DEBUGpic14_emitcode(";","%d",__LINE__);
581         /* if in bit space */
582         if (IN_BITSPACE(space)) {
583                 sym->aop = aop = newAsmop (AOP_CRY);
584                 aop->aopu.aop_dir = sym->rname ;
585                 aop->size = getSize(sym->type);
586                 //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
587                 return aop;
588         }
589         /* if it is in direct space */
590         if (IN_DIRSPACE(space)) {
591                 sym->aop = aop = newAsmop (AOP_DIR);
592                 aop->aopu.aop_dir = sym->rname ;
593                 aop->size = getSize(sym->type);
594                 DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
595                 return aop;
596         }
597         
598         /* special case for a function */
599         if (IS_FUNC(sym->type)) {   
600                 
601                 sym->aop = aop = newAsmop(AOP_PCODE);
602                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
603                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
604                 PCOI(aop->aopu.pcop)->_function = 1;
605                 PCOI(aop->aopu.pcop)->index = 0;
606                 aop->size = FPTRSIZE; 
607                 /*
608                 sym->aop = aop = newAsmop(AOP_IMMD);    
609                 aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
610                 strcpy(aop->aopu.aop_immd,sym->rname);
611                 aop->size = FPTRSIZE; 
612                 */
613                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
614                 return aop;
615         }
616         
617         if (IS_ARRAY(sym->type)) {
618                 sym->aop = aop = newAsmop(AOP_PCODE);
619                 aop->aopu.pcop = popGetImmd(sym->rname,0,0,1);
620                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
621                 PCOI(aop->aopu.pcop)->_function = 0;
622                 PCOI(aop->aopu.pcop)->index = 0;
623                 aop->size = getSize(sym->etype) * DCL_ELEM(sym->type);
624                 
625                 DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
626                 return aop;
627         }
628         
629         /* only remaining is far space */
630         /* in which case DPTR gets the address */
631         sym->aop = aop = newAsmop(AOP_PCODE);
632         
633         aop->aopu.pcop = popGetImmd(sym->rname,0,0,0);
634         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
635         PCOI(aop->aopu.pcop)->index = 0;
636         
637         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
638                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
639         
640         allocDirReg (IC_LEFT(ic));
641         
642         aop->size = FPTRSIZE;
643         /*
644         DEBUGpic14_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
645         sym->aop = aop = newAsmop(AOP_DPTR);
646         pic14_emitcode ("mov","dptr,#%s", sym->rname);
647         aop->size = getSize(sym->type);
648         
649           DEBUGpic14_emitcode(";","%d size = %d",__LINE__,aop->size);
650         */
651         
652         /* if it is in code space */
653         if (IN_CODESPACE(space))
654                 aop->code = 1;
655         
656         return aop;       
657 }
658
659 /*-----------------------------------------------------------------*/
660 /* aopForRemat - rematerialzes an object                                                   */
661 /*-----------------------------------------------------------------*/
662 static asmop *aopForRemat (operand *op) // x symbol *sym)
663 {
664         symbol *sym = OP_SYMBOL(op);
665         iCode *ic = NULL;
666         asmop *aop = newAsmop(AOP_PCODE);
667         int val = 0;
668         int offset = 0;
669         
670         ic = sym->rematiCode;
671
672         DEBUGpic14_emitcode(";","%s %d",__FUNCTION__,__LINE__);
673         if(IS_OP_POINTER(op)) {
674                 DEBUGpic14_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
675         }
676         for (;;) {
677                 if (ic->op == '+') {
678                         val += (int) operandLitValue(IC_RIGHT(ic));
679                 } else if (ic->op == '-') {
680                         val -= (int) operandLitValue(IC_RIGHT(ic));
681                 } else
682                         break;
683                 
684                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
685         }
686         
687         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
688         aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
689         PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
690         PCOI(aop->aopu.pcop)->index = val;
691         
692         DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
693                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
694                 val, IS_PTR_CONST(operandType(op)));
695         
696         //      DEBUGpic14_emitcode(";","aop type  %s",AopType(AOP_TYPE(IC_LEFT(ic))));
697         
698         allocDirReg (IC_LEFT(ic));
699         
700         return aop;              
701 }
702
703 int aopIdx (asmop *aop, int offset)
704 {
705         if(!aop)
706                 return -1;
707         
708         if(aop->type !=  AOP_REG)
709                 return -2;
710         
711         return aop->aopu.aop_reg[offset]->rIdx;
712         
713 }
714 /*-----------------------------------------------------------------*/
715 /* regsInCommon - two operands have some registers in common       */
716 /*-----------------------------------------------------------------*/
717 static bool regsInCommon (operand *op1, operand *op2)
718 {
719         symbol *sym1, *sym2;
720         int i;
721         
722         /* if they have registers in common */
723         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
724                 return FALSE ;
725         
726         sym1 = OP_SYMBOL(op1);
727         sym2 = OP_SYMBOL(op2);
728         
729         if (sym1->nRegs == 0 || sym2->nRegs == 0)
730                 return FALSE ;
731         
732         for (i = 0 ; i < sym1->nRegs ; i++) {
733                 int j;
734                 if (!sym1->regs[i])
735                         continue ;
736                 
737                 for (j = 0 ; j < sym2->nRegs ;j++ ) {
738                         if (!sym2->regs[j])
739                                 continue ;
740                         
741                         if (sym2->regs[j] == sym1->regs[i])
742                                 return TRUE ;
743                 }
744         }
745         
746         return FALSE ;
747 }
748
749 /*-----------------------------------------------------------------*/
750 /* operandsEqu - equivalent                                                                        */
751 /*-----------------------------------------------------------------*/
752 static bool operandsEqu ( operand *op1, operand *op2)
753 {
754         symbol *sym1, *sym2;
755         
756         /* if they not symbols */
757         if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
758                 return FALSE;
759         
760         sym1 = OP_SYMBOL(op1);
761         sym2 = OP_SYMBOL(op2);
762         
763         /* if both are itemps & one is spilt
764         and the other is not then false */
765         if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
766                 sym1->isspilt != sym2->isspilt )
767                 return FALSE ;
768         
769         /* if they are the same */
770         if (sym1 == sym2)
771                 return TRUE ;
772         
773         if (sym1->rname[0] && sym2->rname[0]
774                 && strcmp (sym1->rname, sym2->rname) == 0)
775                 return TRUE;
776         
777         
778         /* if left is a tmp & right is not */
779         if (IS_ITEMP(op1)  && 
780                 !IS_ITEMP(op2) &&
781                 sym1->isspilt  &&
782                 (sym1->usl.spillLoc == sym2))
783                 return TRUE;
784         
785         if (IS_ITEMP(op2)  && 
786                 !IS_ITEMP(op1) &&
787                 sym2->isspilt  &&
788                 sym1->level > 0 &&
789                 (sym2->usl.spillLoc == sym1))
790                 return TRUE ;
791         
792         return FALSE ;
793 }
794
795 /*-----------------------------------------------------------------*/
796 /* pic14_sameRegs - two asmops have the same registers             */
797 /*-----------------------------------------------------------------*/
798 bool pic14_sameRegs (asmop *aop1, asmop *aop2 )
799 {
800         int i;
801         
802         if (aop1 == aop2)
803                 return TRUE ;
804         
805         if (aop1->type != AOP_REG ||
806                 aop2->type != AOP_REG )
807                 return FALSE ;
808         
809         if (aop1->size != aop2->size )
810                 return FALSE ;
811         
812         for (i = 0 ; i < aop1->size ; i++ )
813                 if (aop1->aopu.aop_reg[i] !=
814                         aop2->aopu.aop_reg[i] )
815                         return FALSE ;
816                 
817                 return TRUE ;
818 }
819
820 /*-----------------------------------------------------------------*/
821 /* aopOp - allocates an asmop for an operand  :                    */
822 /*-----------------------------------------------------------------*/
823 void aopOp (operand *op, iCode *ic, bool result)
824 {
825         asmop *aop;
826         symbol *sym;
827         int i;
828         
829         if (!op)
830                 return ;
831         
832         /* if this a literal */
833         if (IS_OP_LITERAL(op)) {
834                 op->aop = aop = newAsmop(AOP_LIT);
835                 aop->aopu.aop_lit = op->operand.valOperand;
836                 aop->size = getSize(operandType(op));
837                 return;
838         }
839         
840         {
841                 sym_link *type = operandType(op);
842                 if(IS_PTR_CONST(type))
843                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
844         }
845         
846         /* if already has a asmop then continue */
847         if (op->aop)
848                 return ;
849         
850         /* if the underlying symbol has a aop */
851         if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
852                 DEBUGpic14_emitcode(";","%d",__LINE__);
853                 op->aop = OP_SYMBOL(op)->aop;
854                 return;
855         }
856         
857         /* if this is a true symbol */
858         if (IS_TRUE_SYMOP(op)) {          
859                 //DEBUGpic14_emitcode(";","%d - true symop",__LINE__);
860                 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
861                 return ;
862         }
863         
864         /* this is a temporary : this has
865         only four choices :
866         a) register
867         b) spillocation
868         c) rematerialize 
869         d) conditional   
870         e) can be a return use only */
871         
872         sym = OP_SYMBOL(op);
873         
874         
875         /* if the type is a conditional */
876         if (sym->regType == REG_CND) {
877                 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
878                 aop->size = 0;
879                 return;
880         }
881         
882         /* if it is spilt then two situations
883         a) is rematerialize 
884         b) has a spill location */
885         if (sym->isspilt || sym->nRegs == 0) {
886                 
887                 DEBUGpic14_emitcode(";","%d",__LINE__);
888                 /* rematerialize it NOW */
889                 if (sym->remat) {
890                         
891                         sym->aop = op->aop = aop = aopForRemat (op);
892                         aop->size = getSize(sym->type);
893                         //DEBUGpic14_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
894                         return;
895                 }
896                 
897 #if 0
898                 /* WREG is not usable as an ordinary operand with PIC architecture,
899                  * one might introduce a scratch register that can be used to make
900                  * WREG accesible as an operand... disable WREG for now */
901                 if (sym->accuse) {
902                         int i;
903                         aop = op->aop = sym->aop = newAsmop(AOP_ACC);
904                         aop->size = getSize(sym->type);
905                         for ( i = 0 ; i < 2 ; i++ )
906                                 aop->aopu.aop_str[i] = accUse[i];
907                         DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size);
908                         return;  
909                 }
910 #endif
911                 
912                 if (sym->ruonly ) {
913                         if(sym->isptr) {        // && sym->uptr 
914                                 aop = op->aop = sym->aop = newAsmop(AOP_PCODE);
915                                 aop->aopu.pcop = newpCodeOp(NULL,PO_GPR_POINTER); //popCopyReg(&pc_fsr);
916                                 
917                                 //PCOI(aop->aopu.pcop)->_const = 0;
918                                 //PCOI(aop->aopu.pcop)->index = 0;
919                                 /*
920                                 DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
921                                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
922                                 */
923                                 //allocDirReg (IC_LEFT(ic));
924                                 
925                                 aop->size = getSize(sym->type);
926                                 DEBUGpic14_emitcode(";","%d",__LINE__);
927                                 return;
928                                 
929                         } else {
930                                 
931                                 unsigned i;
932                                 
933                                 aop = op->aop = sym->aop = newAsmop(AOP_STR);
934                                 aop->size = getSize(sym->type);
935                                 for ( i = 0 ; i < fReturnSizePic ; i++ )
936                                         aop->aopu.aop_str[i] = fReturn[i];
937                                 
938                                 DEBUGpic14_emitcode(";","%d",__LINE__);
939                                 return;
940                         }
941                 }
942                 
943                 /* else spill location  */
944                 if (sym->usl.spillLoc)
945                 {
946                         asmop *oldAsmOp = NULL;
947
948                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
949                         {
950                                 /* force a new aop if sizes differ */
951                                 oldAsmOp = sym->usl.spillLoc->aop;
952                                 sym->usl.spillLoc->aop = NULL;
953                         }
954                         DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
955                                 __FUNCTION__,__LINE__,
956                                 sym->usl.spillLoc->rname,
957                                 sym->rname, sym->usl.spillLoc->offset);
958                 
959                         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
960                         if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
961                         {
962                                 /* Don't reuse the new aop, go with the last one */
963                                 sym->usl.spillLoc->aop = oldAsmOp;
964                         }
965                         //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
966                         aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
967                                 getSize(sym->type), 
968                                 sym->usl.spillLoc->offset);
969                         aop->size = getSize(sym->type);
970                 
971                         return;
972                 }
973         }
974         
975         {
976                 sym_link *type = operandType(op);
977                 if(IS_PTR_CONST(type)) 
978                         DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
979         }
980         
981         /* must be in a register */
982         DEBUGpic14_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
983         sym->aop = op->aop = aop = newAsmop(AOP_REG);
984         aop->size = sym->nRegs;
985         for ( i = 0 ; i < sym->nRegs ;i++)
986                 aop->aopu.aop_reg[i] = sym->regs[i];
987 }
988
989 /*-----------------------------------------------------------------*/
990 /* freeAsmop - free up the asmop given to an operand                       */
991 /*----------------------------------------------------------------*/
992 void freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
993 {       
994         asmop *aop ;
995         
996         if (!op)
997                 aop = aaop;
998         else 
999                 aop = op->aop;
1000         
1001         if (!aop)
1002                 return ;
1003         
1004         if (aop->freed)
1005                 goto dealloc; 
1006         
1007         aop->freed = 1;
1008         
1009         /* depending on the asmop type only three cases need work AOP_RO
1010         , AOP_R1 && AOP_STK */
1011 #if 0
1012         switch (aop->type) {
1013         case AOP_R0 :
1014                 if (_G.r0Pushed ) {
1015                         if (pop) {
1016                                 pic14_emitcode ("pop","ar0");     
1017                                 _G.r0Pushed--;
1018                         }
1019                 }
1020                 bitVectUnSetBit(ic->rUsed,R0_IDX);
1021                 break;
1022                 
1023         case AOP_R1 :
1024                 if (_G.r1Pushed ) {
1025                         if (pop) {
1026                                 pic14_emitcode ("pop","ar1");
1027                                 _G.r1Pushed--;
1028                         }
1029                 }
1030                 bitVectUnSetBit(ic->rUsed,R1_IDX);                      
1031                 break;
1032                 
1033         case AOP_STK :
1034                 {
1035                         int sz = aop->size;      
1036                         int stk = aop->aopu.aop_stk + aop->size;
1037                         bitVectUnSetBit(ic->rUsed,R0_IDX);
1038                         bitVectUnSetBit(ic->rUsed,R1_IDX);                
1039                         
1040                         getFreePtr(ic,&aop,FALSE);
1041                         
1042                         if (options.stack10bit)
1043                         {
1044                                 /* I'm not sure what to do here yet... */
1045                                 /* #STUB */
1046                                 fprintf(stderr, 
1047                                         "*** Warning: probably generating bad code for "
1048                                         "10 bit stack mode.\n");
1049                         }
1050                         
1051                         if (stk) {
1052                                 pic14_emitcode ("mov","a,_bp");
1053                                 pic14_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1054                                 pic14_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1055                         } else {
1056                                 pic14_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1057                         }
1058                         
1059                         while (sz--) {
1060                                 pic14_emitcode("pop","acc");
1061                                 pic14_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1062                                 if (!sz) break;
1063                                 pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1064                         }
1065                         op->aop = aop;
1066                         freeAsmop(op,NULL,ic,TRUE);
1067                         if (_G.r0Pushed) {
1068                                 pic14_emitcode("pop","ar0");
1069                                 _G.r0Pushed--;
1070                         }
1071                         
1072                         if (_G.r1Pushed) {
1073                                 pic14_emitcode("pop","ar1");
1074                                 _G.r1Pushed--;
1075                         }         
1076                 }
1077         }
1078 #endif
1079         
1080 dealloc:
1081         /* all other cases just dealloc */
1082         if (op ) {
1083                 op->aop = NULL;
1084                 if (IS_SYMOP(op)) {
1085                         OP_SYMBOL(op)->aop = NULL;      
1086                         /* if the symbol has a spill */
1087                         if (SPIL_LOC(op))
1088                                 SPIL_LOC(op)->aop = NULL;
1089                 }
1090         }
1091 }
1092
1093 /*-----------------------------------------------------------------*/
1094 /* aopGet - for fetching value of the aop                                                  */
1095 /*-----------------------------------------------------------------*/
1096 char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
1097 {
1098         char *s = buffer ;
1099         char *rs;
1100         
1101         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1102         /* offset is greater than
1103         size then zero */
1104         if (offset > (aop->size - 1) &&
1105                 aop->type != AOP_LIT)
1106                 return zero;
1107         
1108         /* depending on type */
1109         switch (aop->type) {
1110                 
1111         case AOP_R0:
1112         case AOP_R1:
1113                 DEBUGpic14_emitcode(";","%d",__LINE__);
1114                 /* if we need to increment it */           
1115                 while (offset > aop->coff) {            
1116                         pic14_emitcode ("inc","%s",aop->aopu.aop_ptr->name);    
1117                         aop->coff++;
1118                 }
1119                 
1120                 while (offset < aop->coff) {
1121                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1122                         aop->coff--;
1123                 }
1124                 
1125                 aop->coff = offset ;
1126                 if (aop->paged) {
1127                         pic14_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1128                         return (dname ? "acc" : "a");
1129                 }               
1130                 sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1131                 rs = Safe_calloc(1,strlen(s)+1);
1132                 strcpy(rs,s);   
1133                 return rs;
1134                 
1135         case AOP_DPTR:
1136         case AOP_DPTR2:
1137                 DEBUGpic14_emitcode(";","%d",__LINE__);
1138                 if (aop->type == AOP_DPTR2)
1139                 {
1140                         genSetDPTR(1);
1141                 }
1142                 
1143                 while (offset > aop->coff) {
1144                         pic14_emitcode ("inc","dptr");
1145                         aop->coff++;
1146                 }
1147                 
1148                 while (offset < aop->coff) {            
1149                         pic14_emitcode("lcall","__decdptr");
1150                         aop->coff--;
1151                 }
1152                 
1153                 aop->coff = offset;
1154                 if (aop->code) {
1155                         pic14_emitcode("clr","a");
1156                         pic14_emitcode("movc","a,@a+dptr");
1157                 }
1158                 else {
1159                         pic14_emitcode("movx","a,@dptr");
1160                 }
1161                 
1162                 if (aop->type == AOP_DPTR2)
1163                 {
1164                         genSetDPTR(0);
1165                 }
1166                 
1167                 return (dname ? "acc" : "a");
1168                 
1169                 
1170         case AOP_IMMD:
1171                 if (bit16) 
1172                         sprintf (s,"%s",aop->aopu.aop_immd);
1173                 else
1174                         if (offset) 
1175                                 sprintf(s,"(%s >> %d)",
1176                                 aop->aopu.aop_immd,
1177                                 offset*8);
1178                         else
1179                                 sprintf(s,"%s",
1180                                 aop->aopu.aop_immd);
1181                         DEBUGpic14_emitcode(";","%d immd %s",__LINE__,s);
1182                         rs = Safe_calloc(1,strlen(s)+1);
1183                         strcpy(rs,s);   
1184                         return rs;
1185                         
1186         case AOP_DIR:
1187                 if (offset) {
1188                         sprintf(s,"(%s + %d)",
1189                                 aop->aopu.aop_dir,
1190                                 offset);
1191                         DEBUGpic14_emitcode(";","oops AOP_DIR did this %s\n",s);
1192                 } else
1193                         sprintf(s,"%s",aop->aopu.aop_dir);
1194                 rs = Safe_calloc(1,strlen(s)+1);
1195                 strcpy(rs,s);   
1196                 return rs;
1197                 
1198         case AOP_REG:
1199                 //if (dname) 
1200                 //        return aop->aopu.aop_reg[offset]->dname;
1201                 //else
1202                 return aop->aopu.aop_reg[offset]->name;
1203                 
1204         case AOP_CRY:
1205                 //pic14_emitcode(";","%d",__LINE__);
1206                 return aop->aopu.aop_dir;
1207                 
1208         case AOP_ACC:
1209                 DEBUGpic14_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1210                 return "AOP_accumulator_bug";
1211                 
1212         case AOP_LIT:
1213                 sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
1214                 rs = Safe_calloc(1,strlen(s)+1);
1215                 strcpy(rs,s);   
1216                 return rs;
1217                 
1218         case AOP_STR:
1219                 aop->coff = offset ;
1220                 if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1221                         dname)
1222                         return "acc";
1223                 DEBUGpic14_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1224                 
1225                 return aop->aopu.aop_str[offset];
1226                 
1227         case AOP_PCODE:
1228                 {
1229                         pCodeOp *pcop = aop->aopu.pcop;
1230                         DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
1231                         if(pcop->name) {
1232                                 if (offset) {
1233                                         DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
1234                                         sprintf(s,"(%s+%d)", pcop->name,offset);
1235                                 } else {
1236                                         DEBUGpic14_emitcode(";","%s",pcop->name);
1237                                         sprintf(s,"%s", pcop->name);
1238                                 }
1239                         } else
1240                                 sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1241                         
1242                 }
1243                 rs = Safe_calloc(1,strlen(s)+1);
1244                 strcpy(rs,s);   
1245                 return rs;
1246                 
1247   }
1248   
1249   werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1250           "aopget got unsupported aop->type");
1251   exit(0);
1252 }
1253
1254
1255 /*-----------------------------------------------------------------*/
1256 /* popGetTempReg - create a new temporary pCodeOp                                  */
1257 /*-----------------------------------------------------------------*/
1258 pCodeOp *popGetTempReg(void)
1259 {
1260         
1261         pCodeOp *pcop;
1262         
1263         pcop = newpCodeOp(NULL, PO_GPR_TEMP);
1264         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1265                 PCOR(pcop)->r->wasUsed=1;
1266                 PCOR(pcop)->r->isFree=0;
1267         }
1268         
1269         return pcop;
1270 }
1271
1272 /*-----------------------------------------------------------------*/
1273 /* popReleaseTempReg - create a new temporary pCodeOp                              */
1274 /*-----------------------------------------------------------------*/
1275 void popReleaseTempReg(pCodeOp *pcop)
1276 {
1277         
1278         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1279                 PCOR(pcop)->r->isFree = 1;
1280         
1281 }
1282 /*-----------------------------------------------------------------*/
1283 /* popGetLabel - create a new pCodeOp of type PO_LABEL                     */
1284 /*-----------------------------------------------------------------*/
1285 pCodeOp *popGetLabel(unsigned int key)
1286 {
1287         
1288         DEBUGpic14_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1289         
1290         if(key>(unsigned int)max_key)
1291                 max_key = key;
1292         
1293         return newpCodeOpLabel(NULL,key+100+labelOffset);
1294 }
1295
1296 /*-------------------------------------------------------------------*/
1297 /* popGetHighLabel - create a new pCodeOp of type PO_LABEL with offset=1 */
1298 /*-------------------------------------------------------------------*/
1299 pCodeOp *popGetHighLabel(unsigned int key)
1300 {
1301         pCodeOp *pcop;
1302         pcop = popGetLabel(key);
1303         PCOLAB(pcop)->offset = 1;
1304         return pcop;
1305 }
1306
1307 /*-----------------------------------------------------------------*/
1308 /* popGetLit - asm operator to pcode operator conversion                           */
1309 /*-----------------------------------------------------------------*/
1310 pCodeOp *popGetLit(unsigned int lit)
1311 {
1312         
1313         return newpCodeOpLit((unsigned char)lit);
1314 }
1315
1316 /*-----------------------------------------------------------------*/
1317 /* popGetImmd - asm operator to pcode immediate conversion                 */
1318 /*-----------------------------------------------------------------*/
1319 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func)
1320 {
1321         
1322         return newpCodeOpImmd(name, offset,index, 0, is_func);
1323 }
1324
1325 extern set *externs;
1326
1327 /*-----------------------------------------------------------------*/
1328 /* popGetWithString - asm operator to pcode operator conversion                    */
1329 /*-----------------------------------------------------------------*/
1330 pCodeOp *popGetWithString(char *str, int isExtern)
1331 {
1332         pCodeOp *pcop;
1333         
1334         
1335         if(!str) {
1336                 fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1337                 exit (1);
1338         }
1339         
1340         pcop = newpCodeOp(str,PO_STR);
1341         PCOS(pcop)->isPublic = isExtern ? 1 : 0;
1342
1343         return pcop;
1344 }
1345
1346 pCodeOp *popGetExternal (char *str)
1347 {
1348         pCodeOp *pcop = popGetWithString (str, 1);
1349         
1350         if (str) {
1351           symbol *sym;
1352           bool found = 0;
1353
1354           for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
1355           {
1356             if (!strcmp (str, sym->rname))
1357               found = 1;
1358           }
1359           
1360           if (!found)
1361           {
1362             sym = newSymbol(str, 0);
1363             strncpy(sym->rname, str, SDCC_NAME_MAX);
1364             addSet (&externs, sym);
1365           } // if
1366         }
1367         return pcop;
1368 }
1369
1370 /*-----------------------------------------------------------------*/
1371 /* popRegFromString -                                                                                      */
1372 /*-----------------------------------------------------------------*/
1373 pCodeOp *popRegFromString(char *str, int size, int offset)
1374 {
1375         
1376         pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1377         pcop->type = PO_DIR;
1378         
1379         DEBUGpic14_emitcode(";","%d",__LINE__);
1380         
1381         if(!str)
1382                 str = "BAD_STRING";
1383         
1384         pcop->name = Safe_calloc(1,strlen(str)+1);
1385         strcpy(pcop->name,str);
1386         
1387         //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1388         
1389         PCOR(pcop)->r = dirregWithName(pcop->name);
1390         if(PCOR(pcop)->r == NULL) {
1391                 //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1392                 PCOR(pcop)->r = allocRegByName (pcop->name,size);
1393                 DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1394         } else {
1395                 DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1396         }
1397         PCOR(pcop)->instance = offset;
1398         
1399         return pcop;
1400 }
1401
1402 /*-----------------------------------------------------------------*/
1403 /*-----------------------------------------------------------------*/
1404 pCodeOp *popRegFromIdx(int rIdx)
1405 {
1406         pCodeOp *pcop;
1407         
1408         DEBUGpic14_emitcode ("; ***","%s,%d  , rIdx=0x%x",
1409                 __FUNCTION__,__LINE__,rIdx);
1410         
1411         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1412         
1413         PCOR(pcop)->rIdx = rIdx;
1414         PCOR(pcop)->r = typeRegWithIdx(rIdx,REG_STK,1);
1415         PCOR(pcop)->r->isFree = 0;
1416         PCOR(pcop)->r->wasUsed = 1;
1417         
1418         pcop->type = PCOR(pcop)->r->pc_type;
1419         
1420         
1421         return pcop;
1422 }
1423
1424 /*-----------------------------------------------------------------*/
1425 /* popGet - asm operator to pcode operator conversion                      */
1426 /*-----------------------------------------------------------------*/
1427 pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1428 {
1429         //char *s = buffer ;
1430         //char *rs;
1431         
1432         pCodeOp *pcop;
1433         
1434         //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1435         /* offset is greater than
1436         size then zero */
1437
1438         assert (aop);
1439
1440         /* XXX: still needed for BIT operands (AOP_CRY) */
1441         if (offset > (aop->size - 1) &&
1442                 aop->type != AOP_LIT)
1443                 return NULL;  //zero;
1444         
1445         /* depending on type */
1446         switch (aop->type) {
1447                 
1448         case AOP_R0:
1449         case AOP_R1:
1450         case AOP_DPTR:
1451         case AOP_DPTR2:
1452         case AOP_ACC:
1453                 DEBUGpic14_emitcode(";8051 legacy","%d type = %s",__LINE__,AopType(aop->type));
1454                 return NULL;
1455                 
1456         case AOP_IMMD:
1457                 DEBUGpic14_emitcode(";","%d",__LINE__);
1458                 return popGetImmd(aop->aopu.aop_immd,offset,0,0);
1459                 
1460         case AOP_DIR:
1461                 return popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1462 #if 0
1463                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1464                 pcop->type = PO_DIR;
1465                 
1466                 pcop->name = Safe_calloc(1,strlen(aop->aopu.aop_dir)+1);
1467                 strcpy(pcop->name,aop->aopu.aop_dir);   
1468                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1469                 if(PCOR(pcop)->r == NULL) {
1470                         //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size);
1471                         PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size);
1472                         DEBUGpic14_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1473                 } else {
1474                         DEBUGpic14_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1475                 }
1476                 PCOR(pcop)->instance = offset;
1477                 
1478                 return pcop;
1479 #endif
1480                 
1481         case AOP_REG:
1482                 {
1483                         int rIdx;
1484                         assert (offset < aop->size);
1485                         rIdx = aop->aopu.aop_reg[offset]->rIdx;
1486                         
1487                         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1488                         PCOR(pcop)->rIdx = rIdx;
1489                         PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1490                         PCOR(pcop)->r->wasUsed=1;
1491                         PCOR(pcop)->r->isFree=0;
1492                         
1493                         PCOR(pcop)->instance = offset;
1494                         pcop->type = PCOR(pcop)->r->pc_type;
1495                         //rs = aop->aopu.aop_reg[offset]->name;
1496                         DEBUGpic14_emitcode(";","%d rIdx = r0x%X ",__LINE__,rIdx);
1497                         return pcop;
1498                 }
1499                 
1500         case AOP_CRY:
1501                 pcop = newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1502                 PCOR(pcop)->r = dirregWithName(aop->aopu.aop_dir);
1503                 //if(PCOR(pcop)->r == NULL)
1504                 //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1505                 return pcop;
1506                 
1507         case AOP_LIT:
1508                 return newpCodeOpLit(pic14aopLiteral (aop->aopu.aop_lit,offset));
1509                 
1510         case AOP_STR:
1511                 DEBUGpic14_emitcode(";","%d  %s",__LINE__,aop->aopu.aop_str[offset]);
1512                 return newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1513                 /*
1514                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1515                 PCOR(pcop)->r = allocRegByName(aop->aopu.aop_str[offset]);
1516                 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1517                 pcop->type = PCOR(pcop)->r->pc_type;
1518                 pcop->name = PCOR(pcop)->r->name;
1519                 
1520                   return pcop;
1521                 */
1522                 
1523         case AOP_PCODE:
1524                 pcop = NULL;
1525                 DEBUGpic14_emitcode(";","popGet AOP_PCODE (%s + %i) %d %s",pCodeOpType(aop->aopu.pcop), offset,
1526                         __LINE__, 
1527                         ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1528                 //emitpComment ("popGet; name %s, offset: %i, pcop-type: %s\n", aop->aopu.pcop->name, offset, pCodeOpType (aop->aopu.pcop));
1529                 switch (aop->aopu.pcop->type)
1530                 {
1531                 case PO_IMMEDIATE:
1532                   pcop = pCodeOpCopy (aop->aopu.pcop);
1533                   /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1534                    * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1535                   PCOI(pcop)->index += offset;
1536                   //PCOI(pcop)->offset = 0;
1537                   break;
1538                 case PO_DIR:
1539                   pcop = pCodeOpCopy (aop->aopu.pcop);
1540                   PCOR(pcop)->instance = offset;
1541                   break;
1542                 default:
1543                   assert ( !"unhandled pCode type" );
1544                   break;
1545                 } // switch
1546                 return pcop;
1547         }
1548         
1549         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1550                 "popGet got unsupported aop->type");
1551         exit(0);
1552 }
1553
1554 /*-----------------------------------------------------------------*/
1555 /* popGetAddr - access the low/high word of a symbol (immediate)   */
1556 /*              (for non-PO_IMMEDIATEs this is the same as popGet) */
1557 /*-----------------------------------------------------------------*/
1558 pCodeOp *popGetAddr (asmop *aop, int offset, int index)
1559 {
1560   if (aop->type == AOP_PCODE && aop->aopu.pcop->type == PO_IMMEDIATE)
1561   {
1562     pCodeOp *pcop = aop->aopu.pcop;
1563     assert (offset <= GPTRSIZE);
1564
1565     /* special case: index >= 2 should return GPOINTER-style values */
1566     if (offset == 2)
1567     {
1568       pcop = popGetLit (aop->code ? GPTRTAG_CODE : GPTRTAG_DATA);
1569       return pcop;
1570     }
1571     
1572     pcop = pCodeOpCopy (pcop);
1573     /* usually we want to access the memory at "<symbol> + offset" (using ->index),
1574      * but sometimes we want to access the high byte of the symbol's address (using ->offset) */
1575     PCOI(pcop)->offset += offset;
1576     PCOI(pcop)->index += index;
1577     //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);
1578     return pcop;
1579   } else {
1580     return popGet (aop, offset + index);
1581   }
1582 }
1583
1584 /*-----------------------------------------------------------------*/
1585 /* aopPut - puts a string for a aop                                                        */
1586 /*-----------------------------------------------------------------*/
1587 void aopPut (asmop *aop, char *s, int offset)
1588 {
1589         char *d = buffer ;
1590         symbol *lbl ;
1591         
1592         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1593         
1594         if (aop->size && offset > ( aop->size - 1)) {
1595                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1596                         "aopPut got offset > aop->size");
1597                 exit(0);
1598         }
1599         
1600         /* will assign value to value */
1601         /* depending on where it is ofcourse */
1602         switch (aop->type) {
1603         case AOP_DIR:
1604                 if (offset) {
1605                         sprintf(d,"(%s + %d)",
1606                                 aop->aopu.aop_dir,offset);
1607                         fprintf(stderr,"oops aopPut:AOP_DIR did this %s\n",s);
1608                         
1609                 } else
1610                         sprintf(d,"%s",aop->aopu.aop_dir);
1611                 
1612                 if (strcmp(d,s)) {
1613                         DEBUGpic14_emitcode(";","%d",__LINE__);
1614                         if(strcmp(s,"W"))
1615                                 pic14_emitcode("movf","%s,w",s);
1616                         pic14_emitcode("movwf","%s",d);
1617                         
1618                         if(strcmp(s,"W")) {
1619                                 pic14_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1620                                 if(offset >= aop->size) {
1621                                         emitpcode(POC_CLRF,popGet(aop,offset));
1622                                         break;
1623                                 } else {
1624                                         emitpcode(POC_MOVFW, popGetImmd(s,0,offset,0));
1625                                 }
1626                         }
1627                         emitpcode(POC_MOVWF,popGet(aop,offset));
1628                 
1629                 }
1630                 break;
1631                 
1632         case AOP_REG:
1633                 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
1634                         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1635                         /*
1636                         if (*s == '@'             ||
1637                         strcmp(s,"r0") == 0 ||
1638                         strcmp(s,"r1") == 0 ||
1639                         strcmp(s,"r2") == 0 ||
1640                         strcmp(s,"r3") == 0 ||
1641                         strcmp(s,"r4") == 0 ||
1642                         strcmp(s,"r5") == 0 ||
1643                         strcmp(s,"r6") == 0 || 
1644                         strcmp(s,"r7") == 0 )
1645                         pic14_emitcode("mov","%s,%s  ; %d",
1646                         aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1647                         else
1648                         */
1649                         
1650                         if(strcmp(s,"W")==0 )
1651                                 pic14_emitcode("movf","%s,w  ; %d",s,__LINE__);
1652                         
1653                         pic14_emitcode("movwf","%s",
1654                                 aop->aopu.aop_reg[offset]->name);
1655                         
1656                         if(strcmp(s,zero)==0) {
1657                                 emitpcode(POC_CLRF,popGet(aop,offset));
1658                                 
1659                         } else if(strcmp(s,"W")==0) {
1660                                 pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1661                                 pcop->type = PO_GPR_REGISTER;
1662                                 
1663                                 PCOR(pcop)->rIdx = -1;
1664                                 PCOR(pcop)->r = NULL;
1665                                 
1666                                 DEBUGpic14_emitcode(";","%d",__LINE__);
1667                                 pcop->name = Safe_strdup(s);
1668                                 emitpcode(POC_MOVFW,pcop);
1669                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1670                         } else if(strcmp(s,one)==0) {
1671                                 emitpcode(POC_CLRF,popGet(aop,offset));
1672                                 emitpcode(POC_INCF,popGet(aop,offset));
1673                         } else {
1674                                 emitpcode(POC_MOVWF,popGet(aop,offset));
1675                         }
1676                 }
1677                 break;
1678                 
1679         case AOP_DPTR:
1680         case AOP_DPTR2:
1681                 
1682                 if (aop->type == AOP_DPTR2)
1683                 {
1684                         genSetDPTR(1);
1685                 }
1686                 
1687                 if (aop->code) {
1688                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1689                                 "aopPut writting to code space");
1690                         exit(0);
1691                 }
1692                 
1693                 while (offset > aop->coff) {
1694                         aop->coff++;
1695                         pic14_emitcode ("inc","dptr");
1696                 }
1697                 
1698                 while (offset < aop->coff) {
1699                         aop->coff-- ;
1700                         pic14_emitcode("lcall","__decdptr");
1701                 }
1702                 
1703                 aop->coff = offset;
1704                 
1705                 /* if not in accumulater */
1706                 MOVA(s);
1707                 
1708                 pic14_emitcode ("movx","@dptr,a");
1709                 
1710                 if (aop->type == AOP_DPTR2)
1711                 {
1712                         genSetDPTR(0);
1713                 }
1714                 break;
1715                 
1716         case AOP_R0:
1717         case AOP_R1:
1718                 while (offset > aop->coff) {
1719                         aop->coff++;
1720                         pic14_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1721                 }
1722                 while (offset < aop->coff) {
1723                         aop->coff-- ;
1724                         pic14_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1725                 }
1726                 aop->coff = offset;
1727                 
1728                 if (aop->paged) {
1729                         MOVA(s);                         
1730                         pic14_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1731                         
1732                 } else
1733                         if (*s == '@') {
1734                                 MOVA(s);
1735                                 pic14_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1736                         } else
1737                                 if (strcmp(s,"r0") == 0 ||
1738                                         strcmp(s,"r1") == 0 ||
1739                                         strcmp(s,"r2") == 0 ||
1740                                         strcmp(s,"r3") == 0 ||
1741                                         strcmp(s,"r4") == 0 ||
1742                                         strcmp(s,"r5") == 0 ||
1743                                         strcmp(s,"r6") == 0 || 
1744                                         strcmp(s,"r7") == 0 ) {
1745                                         char buffer[10];
1746                                         sprintf(buffer,"a%s",s);
1747                                         pic14_emitcode("mov","@%s,%s",
1748                                                 aop->aopu.aop_ptr->name,buffer);
1749                                 } else
1750                                         pic14_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1751                                 
1752                                 break;
1753                                 
1754         case AOP_STK:
1755                 if (strcmp(s,"a") == 0)
1756                         pic14_emitcode("push","acc");
1757                 else
1758                         pic14_emitcode("push","%s",s);
1759                 
1760                 break;
1761                 
1762         case AOP_CRY:
1763                 /* if bit variable */
1764                 if (!aop->aopu.aop_dir) {
1765                         pic14_emitcode("clr","a");
1766                         pic14_emitcode("rlc","a");
1767                 } else {
1768                         if (s == zero) 
1769                                 pic14_emitcode("clr","%s",aop->aopu.aop_dir);
1770                         else
1771                                 if (s == one)
1772                                         pic14_emitcode("setb","%s",aop->aopu.aop_dir);
1773                                 else
1774                                         if (!strcmp(s,"c"))
1775                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1776                                         else {
1777                                                 lbl = newiTempLabel(NULL);
1778                                                 
1779                                                 if (strcmp(s,"a")) {
1780                                                         MOVA(s);
1781                                                 }
1782                                                 pic14_emitcode("clr","c");
1783                                                 pic14_emitcode("jz","%05d_DS_",lbl->key+100);
1784                                                 pic14_emitcode("cpl","c");
1785                                                 pic14_emitcode("","%05d_DS_:",lbl->key+100);
1786                                                 pic14_emitcode("mov","%s,c",aop->aopu.aop_dir);
1787                                         }
1788                 }
1789                 break;
1790                 
1791         case AOP_STR:
1792                 aop->coff = offset;
1793                 if (strcmp(aop->aopu.aop_str[offset],s))
1794                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1795                 break;
1796                 
1797         case AOP_ACC:
1798                 aop->coff = offset;
1799                 if (!offset && (strcmp(s,"acc") == 0))
1800                         break;
1801                 
1802                 if (strcmp(aop->aopu.aop_str[offset],s))
1803                         pic14_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1804                 break;
1805                 
1806         default :
1807                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1808                         "aopPut got unsupported aop->type");
1809                 exit(0);
1810         }
1811         
1812 }
1813
1814 /*-----------------------------------------------------------------*/
1815 /* mov2w_op - generate either a MOVLW or MOVFW based operand type  */
1816 /*-----------------------------------------------------------------*/
1817 static void mov2w_op (operand *op, int offset)
1818 {
1819         assert (op);
1820         FENTRY;
1821
1822         /* for PO_IMMEDIATEs: use address or value? */
1823         if (op_isLitLike (op))
1824         {
1825                 /* access address of op */
1826                 if (AOP_TYPE(op) != AOP_LIT) { assert (offset < 3); }
1827                 if (IS_SYMOP(op) && IS_GENPTR(OP_SYM_TYPE(op)) && AOP_SIZE(op) < offset)
1828                 {
1829                         if (offset == GPTRSIZE-1)
1830                                 emitpcode (POC_MOVLW, popGetLit (GPTRTAG_DATA));
1831                         else
1832                                 emitpcode (POC_MOVLW, popGetLit (0));
1833                 }
1834                 else
1835                         emitpcode (POC_MOVLW, popGetAddr(AOP(op), offset, 0));
1836         } else {
1837                 /* access value stored in op */
1838                 mov2w (AOP(op), offset);
1839         }
1840 }
1841
1842
1843 /*-----------------------------------------------------------------*/
1844 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1845 /*-----------------------------------------------------------------*/
1846 void mov2w (asmop *aop, int offset)
1847 {
1848         
1849         if(!aop)
1850                 return;
1851         
1852         DEBUGpic14_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1853         
1854         if ( aop_isLitLike (aop) )
1855                 emitpcode(POC_MOVLW,popGetAddr(aop,offset,0));
1856         else
1857                 emitpcode(POC_MOVFW,popGet(aop,offset));
1858         
1859 }
1860
1861 static void movwf (asmop *op, int offset)
1862 {
1863         emitpcode (POC_MOVWF, popGet(op, offset));
1864 }
1865
1866 static pCodeOp *get_argument_pcop (int idx)
1867 {
1868         assert (idx > 0 && "the 0th (first) argument is passed via WREG");
1869         return popRegFromIdx (Gstack_base_addr - (idx - 1));
1870 }
1871
1872 static pCodeOp *get_return_val_pcop (int offset)
1873 {
1874         assert (offset > 0 && "the most significant byte is returned via WREG");
1875         return popRegFromIdx (Gstack_base_addr - (offset - 1));
1876 }
1877
1878 static void pass_argument (operand *op, int offset, int idx)
1879 {
1880         if (op)
1881                 mov2w_op (op, offset);
1882         if (idx != 0)
1883                 emitpcode(POC_MOVWF, get_argument_pcop (idx));
1884 }
1885
1886 static void get_returnvalue (operand *op, int offset, int idx)
1887 {
1888         if (idx != 0)
1889                 emitpcode(POC_MOVFW, get_return_val_pcop (idx));
1890         movwf(AOP(op), offset);
1891 }
1892
1893 static void call_libraryfunc (char *name)
1894 {
1895   /* library code might reside in different page... */
1896   emitpcode (POC_PAGESEL, popGetWithString (name, 1));
1897   /* call the library function */
1898   emitpcode (POC_CALL, popGetExternal (name));
1899   /* might return from different page... */
1900   emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
1901 }
1902 #if 0
1903 /*-----------------------------------------------------------------*/
1904 /* reAdjustPreg - points a register back to where it should        */
1905 /*-----------------------------------------------------------------*/
1906 static void reAdjustPreg (asmop *aop)
1907 {
1908         int size ;
1909         
1910         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1911         aop->coff = 0;
1912         if ((size = aop->size) <= 1)
1913                 return ;
1914         size-- ;
1915         switch (aop->type) {
1916         case AOP_R0 :
1917         case AOP_R1 :
1918                 while (size--)
1919                         pic14_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1920                 break;                  
1921         case AOP_DPTR :
1922         case AOP_DPTR2:
1923                 if (aop->type == AOP_DPTR2)
1924                 {
1925                         genSetDPTR(1);
1926                 } 
1927                 while (size--)
1928                 {
1929                         pic14_emitcode("lcall","__decdptr");
1930                 }
1931                 
1932                 if (aop->type == AOP_DPTR2)
1933                 {
1934                         genSetDPTR(0);
1935                 }
1936                 break;
1937                 
1938         }
1939         
1940 }
1941 #endif
1942
1943
1944 #if 0
1945 /*-----------------------------------------------------------------*/
1946 /* opIsGptr: returns non-zero if the passed operand is             */
1947 /* a generic pointer type.                                         */
1948 /*-----------------------------------------------------------------*/ 
1949 static int opIsGptr(operand *op)
1950 {
1951         sym_link *type = operandType(op);
1952         
1953         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1954         if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1955         {
1956                 return 1;
1957         }
1958         return 0;          
1959 }
1960 #endif
1961
1962 /*-----------------------------------------------------------------*/
1963 /* pic14_getDataSize - get the operand data size                   */
1964 /*-----------------------------------------------------------------*/
1965 int pic14_getDataSize(operand *op)
1966 {
1967         int size;
1968         
1969         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1970         
1971 #if 0
1972         size = getSize(OP_SYM_ETYPE(op));
1973         return size;
1974         //return AOP_SIZE(op);
1975         
1976         // tsd- in the pic port, the genptr size is 1, so this code here
1977         // fails. ( in the 8051 port, the size was 4).
1978 #else
1979         size = AOP_SIZE(op);
1980         if (IS_GENPTR(OP_SYM_TYPE(op)))
1981         {
1982                 sym_link *type = operandType(op);
1983                 if (IS_GENPTR(type))
1984                 {
1985                         /* generic pointer; arithmetic operations
1986                         * should ignore the high byte (pointer type).
1987                         */
1988                         size--;
1989                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1990                 }
1991         }
1992         return size;
1993 #endif
1994 }
1995
1996 /*-----------------------------------------------------------------*/
1997 /* pic14_outAcc - output Acc                                       */
1998 /*-----------------------------------------------------------------*/
1999 void pic14_outAcc(operand *result)
2000 {
2001         int size,offset;
2002         DEBUGpic14_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2003         DEBUGpic14_AopType(__LINE__,NULL,NULL,result);
2004         
2005         
2006         size = pic14_getDataSize(result);
2007         if(size){
2008                 emitpcode(POC_MOVWF,popGet(AOP(result),0));
2009                 size--;
2010                 offset = 1;
2011                 /* unsigned or positive */
2012                 while(size--)
2013                         emitpcode(POC_CLRF,popGet(AOP(result),offset++));
2014         }
2015         
2016 }
2017
2018 /*-----------------------------------------------------------------*/
2019 /* pic14_outBitC - output a bit C                                  */
2020 /*-----------------------------------------------------------------*/
2021 void pic14_outBitC(operand *result)
2022 {
2023         
2024         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2025         /* if the result is bit */
2026         if (AOP_TYPE(result) == AOP_CRY) 
2027                 aopPut(AOP(result),"c",0);
2028         else {
2029                 pic14_emitcode("clr","a  ; %d", __LINE__);
2030                 pic14_emitcode("rlc","a");
2031                 pic14_outAcc(result);
2032         }
2033 }
2034
2035 /*-----------------------------------------------------------------*/
2036 /* pic14_toBoolean - emit code for orl a,operator(sizeop)          */
2037 /*-----------------------------------------------------------------*/
2038 void pic14_toBoolean(operand *oper)
2039 {
2040         int size = AOP_SIZE(oper);
2041         int offset = 0;
2042         
2043         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2044
2045         assert (size > 0);
2046
2047         if (size == 1) {
2048                 /* MOVFW does not load the flags... */
2049                 if (AOP_TYPE(oper) == AOP_ACC) {
2050                         emitpcode(POC_IORLW, popGetLit(0));
2051                         offset = 1;
2052                 } else {
2053                         emitpcode(POC_MOVLW, popGetLit(0));
2054                         offset = 0;
2055                 }
2056         } else {
2057                 if ( AOP_TYPE(oper) != AOP_ACC) {
2058                         emitpcode(POC_MOVFW,popGet(AOP(oper),0));
2059                         offset = 1;
2060                 }
2061         }
2062         
2063         while (offset < size) {
2064                 emitpcode(POC_IORFW, popGet(AOP(oper),offset++));
2065         }
2066         /* Z is set iff (oper == 0) */
2067 }
2068
2069
2070 /*-----------------------------------------------------------------*/
2071 /* genNot - generate code for ! operation                          */
2072 /*-----------------------------------------------------------------*/
2073 static void genNot (iCode *ic)
2074 {
2075         //symbol *tlbl;
2076         int size;
2077
2078         FENTRY;
2079         
2080         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2081         /* assign asmOps to operand & result */
2082         aopOp (IC_LEFT(ic),ic,FALSE);
2083         aopOp (IC_RESULT(ic),ic,TRUE);
2084         
2085         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2086         /* if in bit space then a special case */
2087         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2088                 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2089                         emitpcode(POC_MOVLW,popGet(AOP(IC_LEFT(ic)),0));
2090                         emitpcode(POC_XORWF,popGet(AOP(IC_RESULT(ic)),0));
2091                 } else {
2092                         emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
2093                         emitpcode(POC_BTFSS,popGet(AOP(IC_LEFT(ic)),0));
2094                         emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
2095                 }
2096                 goto release;
2097         }
2098         
2099         size = AOP_SIZE(IC_LEFT(ic));
2100         mov2w (AOP(IC_LEFT(ic)),0);
2101         while (--size > 0)
2102         {
2103           if (op_isLitLike (IC_LEFT(ic)))
2104             emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
2105           else
2106             emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
2107         }
2108         emitpcode(POC_MOVLW, popGetLit (0));
2109         emitSKPNZ;
2110         emitpcode(POC_MOVLW, popGetLit (1));
2111         movwf(AOP(IC_RESULT(ic)), 0);
2112
2113         for (size = 1; size < AOP_SIZE(IC_RESULT(ic)); size++)
2114         {
2115           emitpcode(POC_CLRF, popGet (AOP(IC_RESULT(ic)), size));
2116         }
2117         goto release;
2118         
2119 release:        
2120         /* release the aops */
2121         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2122         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2123 }
2124
2125
2126 /*-----------------------------------------------------------------*/
2127 /* genCpl - generate code for complement                                                   */
2128 /*-----------------------------------------------------------------*/
2129 static void genCpl (iCode *ic)
2130 {
2131         operand *left, *result;
2132         int size, offset=0;  
2133         
2134         FENTRY;
2135         
2136         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2137         aopOp((left = IC_LEFT(ic)),ic,FALSE);
2138         aopOp((result=IC_RESULT(ic)),ic,TRUE);
2139         
2140         /* if both are in bit space then 
2141         a special case */
2142         if (AOP_TYPE(result) == AOP_CRY &&
2143                 AOP_TYPE(left) == AOP_CRY ) { 
2144                 
2145                 pic14_emitcode("mov","c,%s",left->aop->aopu.aop_dir); 
2146                 pic14_emitcode("cpl","c"); 
2147                 pic14_emitcode("mov","%s,c",result->aop->aopu.aop_dir); 
2148                 goto release; 
2149         } 
2150         
2151         size = AOP_SIZE(result);
2152         if (AOP_SIZE(left) < size) size = AOP_SIZE(left);
2153         while (size--) {
2154                 
2155                 if(AOP_TYPE(left) == AOP_ACC) 
2156                         emitpcode(POC_XORLW, popGetLit(0xff));
2157                 else
2158                         emitpcode(POC_COMFW,popGet(AOP(left),offset));
2159                 
2160                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
2161                 offset++;
2162         }
2163         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
2164         
2165         
2166 release:
2167         /* release the aops */
2168         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2169         freeAsmop(result,NULL,ic,TRUE);
2170 }
2171
2172 /*-----------------------------------------------------------------*/
2173 /* genUminusFloat - unary minus for floating points                        */
2174 /*-----------------------------------------------------------------*/
2175 static void genUminusFloat(operand *op,operand *result)
2176 {
2177         int size ,offset =0 ;
2178         char *l;
2179         
2180         FENTRY;
2181
2182         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2183         /* for this we just need to flip the 
2184         first it then copy the rest in place */
2185         size = AOP_SIZE(op) - 1;
2186         l = aopGet(AOP(op),3,FALSE,FALSE);
2187         
2188         MOVA(l);          
2189         
2190         pic14_emitcode("cpl","acc.7");
2191         aopPut(AOP(result),"a",3);      
2192         
2193         while(size--) {
2194                 aopPut(AOP(result),
2195                         aopGet(AOP(op),offset,FALSE,FALSE),
2196                         offset);
2197                 offset++;
2198         }                
2199 }
2200
2201 /*-----------------------------------------------------------------*/
2202 /* genUminus - unary minus code generation                                                 */
2203 /*-----------------------------------------------------------------*/
2204 static void genUminus (iCode *ic)
2205 {
2206         int size, i;
2207         sym_link *optype, *rtype;
2208         
2209         FENTRY;
2210         
2211         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2212         /* assign asmops */
2213         aopOp(IC_LEFT(ic),ic,FALSE);
2214         aopOp(IC_RESULT(ic),ic,TRUE);
2215         
2216         /* if both in bit space then special
2217         case */
2218         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2219                 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2220                 
2221                 emitpcode(POC_BCF,       popGet(AOP(IC_RESULT(ic)),0));
2222                 emitpcode(POC_BTFSS, popGet(AOP(IC_LEFT(ic)),0));
2223                 emitpcode(POC_BSF,       popGet(AOP(IC_RESULT(ic)),0));
2224                 
2225                 goto release; 
2226         } 
2227         
2228         optype = operandType(IC_LEFT(ic));
2229         rtype = operandType(IC_RESULT(ic));
2230         
2231         /* if float then do float stuff */
2232         if (IS_FLOAT(optype)) {
2233                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2234                 goto release;
2235         }
2236         
2237         /* otherwise subtract from zero by taking the 2's complement */
2238         size = AOP_SIZE(IC_LEFT(ic));
2239         
2240         for(i=0; i<size; i++) {
2241                 if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2242                         emitpcode(POC_COMF,  popGet(AOP(IC_LEFT(ic)),i));
2243                 else {
2244                         emitpcode(POC_COMFW, popGet(AOP(IC_LEFT(ic)),i));
2245                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),i));
2246                 }
2247         }
2248         
2249         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
2250         for(i=1; i<size; i++) {
2251                 emitSKPNZ;
2252                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),i));
2253         }
2254         
2255 release:
2256         /* release the aops */
2257         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2258         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);  
2259 }
2260
2261 /*-----------------------------------------------------------------*/
2262 /* saveRegisters - will look for a call and save the registers     */
2263 /*-----------------------------------------------------------------*/
2264 static void saveRegisters(iCode *lic) 
2265 {
2266         int i;
2267         iCode *ic;
2268         bitVect *rsave;
2269         sym_link *dtype;
2270         
2271         FENTRY;
2272
2273         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2274         /* look for call */
2275         for (ic = lic ; ic ; ic = ic->next) 
2276                 if (ic->op == CALL || ic->op == PCALL)
2277                         break;
2278                 
2279                 if (!ic) {
2280                         fprintf(stderr,"found parameter push with no function call\n");
2281                         return ;
2282                 }
2283                 
2284                 /* if the registers have been saved already then
2285                 do nothing */
2286                 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2287                         return ;
2288                 
2289                         /* find the registers in use at this time 
2290                 and push them away to safety */
2291                 rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2292                         ic->rUsed);
2293                 
2294                 ic->regsSaved = 1;
2295                 if (options.useXstack) {
2296                         if (bitVectBitValue(rsave,R0_IDX))
2297                                 pic14_emitcode("mov","b,r0");
2298                         pic14_emitcode("mov","r0,%s",spname);
2299                         for (i = 0 ; i < pic14_nRegs ; i++) {
2300                                 if (bitVectBitValue(rsave,i)) {
2301                                         if (i == R0_IDX)
2302                                                 pic14_emitcode("mov","a,b");
2303                                         else
2304                                                 pic14_emitcode("mov","a,%s",pic14_regWithIdx(i)->name);
2305                                         pic14_emitcode("movx","@r0,a");
2306                                         pic14_emitcode("inc","r0");
2307                                 }
2308                         }
2309                         pic14_emitcode("mov","%s,r0",spname);
2310                         if (bitVectBitValue(rsave,R0_IDX))
2311                                 pic14_emitcode("mov","r0,b");     
2312                 }// else
2313                 //for (i = 0 ; i < pic14_nRegs ; i++) {
2314                 //        if (bitVectBitValue(rsave,i))
2315                 //      pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
2316                 //}
2317                 
2318                 dtype = operandType(IC_LEFT(ic));
2319                 if (currFunc && dtype && 
2320                         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2321                         IFFUNC_ISISR(currFunc->type) &&
2322                         !ic->bankSaved) 
2323                         
2324                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2325                 
2326 }
2327 /*-----------------------------------------------------------------*/
2328 /* unsaveRegisters - pop the pushed registers                                      */
2329 /*-----------------------------------------------------------------*/
2330 static void unsaveRegisters (iCode *ic)
2331 {
2332         int i;
2333         bitVect *rsave;
2334         
2335         FENTRY;
2336
2337         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2338         /* find the registers in use at this time 
2339         and push them away to safety */
2340         rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2341                 ic->rUsed);
2342         
2343         if (options.useXstack) {
2344                 pic14_emitcode("mov","r0,%s",spname); 
2345                 for (i =  pic14_nRegs ; i >= 0 ; i--) {
2346                         if (bitVectBitValue(rsave,i)) {
2347                                 pic14_emitcode("dec","r0");
2348                                 pic14_emitcode("movx","a,@r0");
2349                                 if (i == R0_IDX)
2350                                         pic14_emitcode("mov","b,a");
2351                                 else
2352                                         pic14_emitcode("mov","%s,a",pic14_regWithIdx(i)->name);
2353                         }       
2354                         
2355                 }
2356                 pic14_emitcode("mov","%s,r0",spname);
2357                 if (bitVectBitValue(rsave,R0_IDX))
2358                         pic14_emitcode("mov","r0,b");
2359         } //else
2360         //for (i =  pic14_nRegs ; i >= 0 ; i--) {
2361         //      if (bitVectBitValue(rsave,i))
2362         //  pic14_emitcode("pop","%s",pic14_regWithIdx(i)->dname);
2363         //}
2364         
2365 }  
2366
2367
2368 /*-----------------------------------------------------------------*/
2369 /* pushSide -                            */
2370 /*-----------------------------------------------------------------*/
2371 static void pushSide(operand * oper, int size)
2372 {
2373 #if 0
2374         int offset = 0;
2375         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2376         while (size--) {
2377                 char *l = aopGet(AOP(oper),offset++,FALSE,TRUE);
2378                 if (AOP_TYPE(oper) != AOP_REG &&
2379                         AOP_TYPE(oper) != AOP_DIR &&
2380                         strcmp(l,"a") ) {
2381                         pic14_emitcode("mov","a,%s",l);
2382                         pic14_emitcode("push","acc");
2383                 } else
2384                         pic14_emitcode("push","%s",l);
2385         }
2386 #endif
2387 }
2388
2389 /*-----------------------------------------------------------------*/
2390 /* assignResultValue -                           */
2391 /*-----------------------------------------------------------------*/
2392 static void assignResultValue(operand * oper)
2393 {
2394         int size = AOP_SIZE(oper);
2395         int offset = 0;
2396         
2397         FENTRY;
2398
2399         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2400         
2401         DEBUGpic14_AopType(__LINE__,oper,NULL,NULL);
2402         
2403         /* assign MSB first (passed via WREG) */
2404         while (size--) {
2405                 get_returnvalue (oper, size, offset + GpsuedoStkPtr);
2406                 GpsuedoStkPtr++;
2407         }
2408 }
2409
2410
2411 /*-----------------------------------------------------------------*/
2412 /* genIpush - genrate code for pushing this gets a little complex  */
2413 /*-----------------------------------------------------------------*/
2414 static void genIpush (iCode *ic)
2415 {
2416         FENTRY;
2417         
2418         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2419 #if 0
2420         int size, offset = 0 ;
2421         char *l;
2422         
2423         
2424         /* if this is not a parm push : ie. it is spill push 
2425         and spill push is always done on the local stack */
2426         if (!ic->parmPush) {
2427                 
2428                 /* and the item is spilt then do nothing */
2429                 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2430                         return ;
2431                 
2432                 aopOp(IC_LEFT(ic),ic,FALSE);
2433                 size = AOP_SIZE(IC_LEFT(ic));
2434                 /* push it on the stack */
2435                 while(size--) {
2436                         l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2437                         if (*l == '#') {
2438                                 MOVA(l);
2439                                 l = "acc";
2440                         }
2441                         pic14_emitcode("push","%s",l);
2442                 }
2443                 return ;                
2444         }
2445         
2446         /* this is a paramter push: in this case we call
2447         the routine to find the call and save those
2448         registers that need to be saved */   
2449         saveRegisters(ic);
2450         
2451         /* then do the push */
2452         aopOp(IC_LEFT(ic),ic,FALSE);
2453         
2454         
2455         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2456         size = AOP_SIZE(IC_LEFT(ic));
2457         
2458         while (size--) {
2459                 l = aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2460                 if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2461                         AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2462                         strcmp(l,"a") ) {
2463                         pic14_emitcode("mov","a,%s",l);
2464                         pic14_emitcode("push","acc");
2465                 } else
2466                         pic14_emitcode("push","%s",l);
2467         }         
2468         
2469         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2470 #endif
2471 }
2472
2473 /*-----------------------------------------------------------------*/
2474 /* genIpop - recover the registers: can happen only for spilling   */
2475 /*-----------------------------------------------------------------*/
2476 static void genIpop (iCode *ic)
2477 {
2478         FENTRY;
2479
2480         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2481         assert (!"genIpop -- unimplemented");
2482 #if 0
2483         int size,offset ;
2484         
2485         
2486         /* if the temp was not pushed then */
2487         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2488                 return ;
2489         
2490         aopOp(IC_LEFT(ic),ic,FALSE);
2491         size = AOP_SIZE(IC_LEFT(ic));
2492         offset = (size-1);
2493         while (size--) 
2494                 pic14_emitcode("pop","%s",aopGet(AOP(IC_LEFT(ic)),offset--,
2495                 FALSE,TRUE));
2496         
2497         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2498 #endif
2499 }
2500
2501 /*-----------------------------------------------------------------*/
2502 /* unsaverbank - restores the resgister bank from stack                    */
2503 /*-----------------------------------------------------------------*/
2504 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2505 {
2506         FENTRY;
2507
2508         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2509 #if 0
2510         int i;
2511         asmop *aop ;
2512         regs *r = NULL;
2513         
2514         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2515         if (popPsw) {
2516                 if (options.useXstack) {
2517                         aop = newAsmop(0);
2518                         r = getFreePtr(ic,&aop,FALSE);
2519                         
2520                         
2521                         pic14_emitcode("mov","%s,_spx",r->name);
2522                         pic14_emitcode("movx","a,@%s",r->name);
2523                         pic14_emitcode("mov","psw,a");
2524                         pic14_emitcode("dec","%s",r->name);
2525                         
2526                 }else
2527                         pic14_emitcode ("pop","psw");
2528         }
2529         
2530         for (i = (pic14_nRegs - 1) ; i >= 0 ;i--) {
2531                 if (options.useXstack) {           
2532                         pic14_emitcode("movx","a,@%s",r->name);
2533                         //pic14_emitcode("mov","(%s+%d),a",
2534                         //         regspic14[i].base,8*bank+regspic14[i].offset);
2535                         pic14_emitcode("dec","%s",r->name);
2536                         
2537                 } else 
2538                         pic14_emitcode("pop",""); //"(%s+%d)",
2539                 //regspic14[i].base,8*bank); //+regspic14[i].offset);
2540         }
2541         
2542         if (options.useXstack) {
2543                 
2544                 pic14_emitcode("mov","_spx,%s",r->name);
2545                 freeAsmop(NULL,aop,ic,TRUE);
2546                 
2547         }
2548 #endif 
2549 }
2550
2551 /*-----------------------------------------------------------------*/
2552 /* saverbank - saves an entire register bank on the stack                  */
2553 /*-----------------------------------------------------------------*/
2554 static void saverbank (int bank, iCode *ic, bool pushPsw)
2555 {
2556         FENTRY;
2557
2558         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2559 #if 0
2560         int i;
2561         asmop *aop ;
2562         regs *r = NULL;
2563         
2564         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2565         if (options.useXstack) {
2566                 
2567                 aop = newAsmop(0);
2568                 r = getFreePtr(ic,&aop,FALSE);  
2569                 pic14_emitcode("mov","%s,_spx",r->name);
2570                 
2571         }
2572         
2573         for (i = 0 ; i < pic14_nRegs ;i++) {
2574                 if (options.useXstack) {
2575                         pic14_emitcode("inc","%s",r->name);
2576                         //pic14_emitcode("mov","a,(%s+%d)",
2577                         //               regspic14[i].base,8*bank+regspic14[i].offset);
2578                         pic14_emitcode("movx","@%s,a",r->name);                 
2579                 } else 
2580                         pic14_emitcode("push","");// "(%s+%d)",
2581                 //regspic14[i].base,8*bank+regspic14[i].offset);
2582         }
2583         
2584         if (pushPsw) {
2585                 if (options.useXstack) {
2586                         pic14_emitcode("mov","a,psw");
2587                         pic14_emitcode("movx","@%s,a",r->name); 
2588                         pic14_emitcode("inc","%s",r->name);
2589                         pic14_emitcode("mov","_spx,%s",r->name);                 
2590                         freeAsmop (NULL,aop,ic,TRUE);
2591                         
2592                 } else
2593                         pic14_emitcode("push","psw");
2594                 
2595                 pic14_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2596         }
2597         ic->bankSaved = 1;
2598 #endif
2599 }
2600
2601 /*-----------------------------------------------------------------*/
2602 /* genCall - generates a call statement                                                    */
2603 /*-----------------------------------------------------------------*/
2604 static void genCall (iCode *ic)
2605 {
2606         sym_link *dtype;         
2607         symbol *sym;
2608         char *name;
2609         int isExtern;
2610         
2611         FENTRY;
2612
2613         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2614         
2615         /* if caller saves & we have not saved then */
2616         if (!ic->regsSaved)
2617                 saveRegisters(ic);
2618         
2619                 /* if we are calling a function that is not using
2620                 the same register bank then we need to save the
2621         destination registers on the stack */
2622         dtype = operandType(IC_LEFT(ic));
2623         if (currFunc && dtype && 
2624                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2625                 IFFUNC_ISISR(currFunc->type) &&
2626                 !ic->bankSaved) 
2627                 
2628                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2629         
2630         /* if send set is not empty the assign */
2631         if (_G.sendSet) {
2632                 iCode *sic;
2633                 /* For the Pic port, there is no data stack.
2634                 * So parameters passed to functions are stored
2635                 * in registers. (The pCode optimizer will get
2636                 * rid of most of these :).
2637                 */
2638                 int psuedoStkPtr=-1;
2639                 int firstTimeThruLoop = 1;
2640                 
2641                 _G.sendSet = reverseSet(_G.sendSet);
2642                 
2643                 /* First figure how many parameters are getting passed */
2644                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2645                 sic = setNextItem(_G.sendSet)) {
2646                         
2647                         aopOp(IC_LEFT(sic),sic,FALSE);
2648                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2649                         freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2650                 }
2651                 
2652                 for (sic = setFirstItem(_G.sendSet) ; sic ; 
2653                 sic = setNextItem(_G.sendSet)) {
2654                         int size, offset = 0;
2655                         
2656                         aopOp(IC_LEFT(sic),sic,FALSE);
2657                         size = AOP_SIZE(IC_LEFT(sic));
2658                         
2659                         while (size--) {
2660                                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2661                                         AopType(AOP_TYPE(IC_LEFT(sic))));
2662                                 
2663                                 if(!firstTimeThruLoop) {
2664                                         /* If this is not the first time we've been through the loop
2665                                         * then we need to save the parameter in a temporary
2666                                         * register. The last byte of the last parameter is
2667                                         * passed in W. */
2668                                         emitpcode(POC_MOVWF,popRegFromIdx(Gstack_base_addr - --psuedoStkPtr));
2669                                         
2670                                 }
2671                                 firstTimeThruLoop=0;
2672                                 
2673                                 mov2w_op (IC_LEFT(sic),  offset);
2674                                 offset++;
2675                         }
2676                         freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2677                 }
2678                 _G.sendSet = NULL;
2679         }
2680         /* make the call */
2681         sym = OP_SYMBOL(IC_LEFT(ic));
2682         name = sym->rname[0] ? sym->rname : sym->name;
2683         isExtern = IS_EXTERN(sym->etype);
2684         if (isExtern) {
2685                 emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
2686         }
2687         emitpcode(POC_CALL,popGetWithString(name,isExtern));
2688         if (isExtern) {
2689                 emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
2690         }
2691         GpsuedoStkPtr=0;
2692         /* if we need assign a result value */
2693         if ((IS_ITEMP(IC_RESULT(ic)) && 
2694                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2695                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2696                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2697                 
2698                 _G.accInUse++;
2699                 aopOp(IC_RESULT(ic),ic,FALSE);
2700                 _G.accInUse--;
2701                 
2702                 assignResultValue(IC_RESULT(ic));
2703                 
2704                 DEBUGpic14_emitcode ("; ","%d left %s",__LINE__,
2705                         AopType(AOP_TYPE(IC_RESULT(ic))));
2706                 
2707                 freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2708         }
2709         
2710         /* if register bank was saved then pop them */
2711         if (ic->bankSaved)
2712                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2713         
2714         /* if we hade saved some registers then unsave them */
2715         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2716                 unsaveRegisters (ic);
2717         
2718         
2719 }
2720
2721 /*-----------------------------------------------------------------*/
2722 /* genPcall - generates a call by pointer statement                        */
2723 /*-----------------------------------------------------------------*/
2724 static void genPcall (iCode *ic)
2725 {
2726         sym_link *dtype;
2727         symbol *albl = newiTempLabel(NULL);
2728         symbol *blbl = newiTempLabel(NULL);
2729         PIC_OPCODE poc;
2730         pCodeOp *pcop;
2731         operand *left;
2732         
2733         FENTRY;
2734
2735         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2736         /* if caller saves & we have not saved then */
2737         if (!ic->regsSaved)
2738                 saveRegisters(ic);
2739         
2740                 /* if we are calling a function that is not using
2741                 the same register bank then we need to save the
2742         destination registers on the stack */
2743         dtype = operandType(IC_LEFT(ic));
2744         if (currFunc && dtype && 
2745                 IFFUNC_ISISR(currFunc->type) &&
2746                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2747                 saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2748         
2749         left = IC_LEFT(ic);
2750         aopOp(left,ic,FALSE);
2751         DEBUGpic14_AopType(__LINE__,left,NULL,NULL);
2752         
2753         poc = ( op_isLitLike (IC_LEFT(ic)) ? POC_MOVLW : POC_MOVFW );
2754         
2755         pushSide(IC_LEFT(ic), FPTRSIZE);
2756         
2757         /* if send set is not empty, assign parameters */
2758         if (_G.sendSet) {
2759                 
2760                 DEBUGpic14_emitcode ("; ***","%s  %d - WARNING arg-passing to indirect call not supported",__FUNCTION__,__LINE__);
2761                 /* no way to pass args - W always gets used to make the call */
2762         }
2763         /* first idea - factor out a common helper function and call it.
2764         But don't know how to get it generated only once in its own block
2765         
2766         if(AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) {
2767                 char *rname;
2768                 char *buffer;
2769                 rname = IC_LEFT(ic)->aop->aopu.aop_dir;
2770                 DEBUGpic14_emitcode ("; ***","%s  %d AOP_DIR %s",__FUNCTION__,__LINE__,rname);
2771                 buffer = Safe_calloc(1,strlen(rname)+16);
2772                 sprintf(buffer, "%s_goto_helper", rname);
2773                 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp(buffer,PO_STR)));
2774                 free(buffer);
2775         }
2776         */
2777         emitpcode(POC_CALL,popGetLabel(albl->key));
2778         pcop = popGetLabel(blbl->key);
2779         emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
2780         emitpcode(POC_GOTO,pcop);
2781         emitpLabel(albl->key);
2782         
2783         emitpcode(poc,popGetAddr(AOP(left),1,0));
2784         emitpcode(POC_MOVWF,popCopyReg(&pc_pclath));
2785         emitpcode(poc,popGetAddr(AOP(left),0,0));
2786         emitpcode(POC_MOVWF,popCopyReg(&pc_pcl));
2787         
2788         emitpLabel(blbl->key);
2789         
2790         freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2791         
2792         /* if we need to assign a result value */
2793         if ((IS_ITEMP(IC_RESULT(ic)) &&
2794                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2795                 OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2796                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2797                 
2798                 _G.accInUse++;
2799                 aopOp(IC_RESULT(ic),ic,FALSE);
2800                 _G.accInUse--;
2801
2802                 GpsuedoStkPtr = 0;
2803                 
2804                 assignResultValue(IC_RESULT(ic));
2805                 
2806                 freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2807         }
2808         
2809         /* if register bank was saved then unsave them */
2810         if (currFunc && dtype && 
2811                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2812                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2813         
2814                 /* if we hade saved some registers then
2815         unsave them */
2816         if (ic->regsSaved)
2817                 unsaveRegisters (ic);
2818         
2819 }
2820
2821 /*-----------------------------------------------------------------*/
2822 /* resultRemat - result  is rematerializable                                       */
2823 /*-----------------------------------------------------------------*/
2824 static int resultRemat (iCode *ic)
2825 {
2826         //      DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2827         FENTRY;
2828
2829         if (SKIP_IC(ic) || ic->op == IFX)
2830                 return 0;
2831         
2832         if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2833                 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2834                 if (sym->remat && !POINTER_SET(ic)) 
2835                         return 1;
2836         }
2837         
2838         return 0;
2839 }
2840
2841 #if defined(__BORLANDC__) || defined(_MSC_VER)
2842 #define STRCASECMP stricmp
2843 #else
2844 #define STRCASECMP strcasecmp
2845 #endif
2846
2847 #if 0
2848 /*-----------------------------------------------------------------*/
2849 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2850 /*-----------------------------------------------------------------*/
2851 static bool inExcludeList(char *s)
2852 {
2853         DEBUGpic14_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2854         int i =0;
2855         
2856         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2857         if (options.excludeRegs[i] &&
2858                 STRCASECMP(options.excludeRegs[i],"none") == 0)
2859                 return FALSE ;
2860         
2861         for ( i = 0 ; options.excludeRegs[i]; i++) {
2862                 if (options.excludeRegs[i] &&
2863                         STRCASECMP(s,options.excludeRegs[i]) == 0)
2864                         return TRUE;
2865         }
2866         return FALSE ;
2867 }
2868 #endif
2869
2870 /*-----------------------------------------------------------------*/
2871 /* genFunction - generated code for function entry                                 */
2872 /*-----------------------------------------------------------------*/
2873 static void genFunction (iCode *ic)
2874 {
2875         symbol *sym;
2876         sym_link *ftype;
2877         
2878         FENTRY;
2879
2880         DEBUGpic14_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2881         
2882         labelOffset += (max_key+4);
2883         max_key=0;
2884         GpsuedoStkPtr=0;
2885         _G.nRegsSaved = 0;
2886         /* create the function header */
2887         pic14_emitcode(";","-----------------------------------------");
2888         pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2889         pic14_emitcode(";","-----------------------------------------");
2890         
2891         pic14_emitcode("","%s:",sym->rname);
2892         addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
2893         
2894         ftype = operandType(IC_LEFT(ic));
2895         
2896         /* if critical function then turn interrupts off */
2897         if (IFFUNC_ISCRITICAL(ftype))
2898                 pic14_emitcode("clr","ea");
2899         
2900                 /* here we need to generate the equates for the
2901         register bank if required */
2902 #if 0
2903         if (FUNC_REGBANK(ftype) != rbank) {
2904                 int i ;
2905                 
2906                 rbank = FUNC_REGBANK(ftype);
2907                 for ( i = 0 ; i < pic14_nRegs ; i++ ) {
2908                         if (strcmp(regspic14[i].base,"0") == 0)
2909                                 pic14_emitcode("","%s = 0x%02x",
2910                                 regspic14[i].dname,
2911                                 8*rbank+regspic14[i].offset);
2912                         else
2913                                 pic14_emitcode ("","%s = %s + 0x%02x",
2914                                 regspic14[i].dname,
2915                                 regspic14[i].base,
2916                                 8*rbank+regspic14[i].offset);
2917                 }
2918         }
2919 #endif
2920         
2921         /* if this is an interrupt service routine */
2922         if (IFFUNC_ISISR(sym->type)) {
2923         /*  already done in pic14createInterruptVect() - delete me
2924         addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
2925         emitpcodeNULLop(POC_NOP);
2926         emitpcodeNULLop(POC_NOP);
2927         emitpcodeNULLop(POC_NOP);
2928                 */
2929                 emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
2930                 emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
2931                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
2932                 emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
2933                 emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
2934                 emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
2935                 emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
2936                 
2937                 pBlockConvert2ISR(pb);
2938                 pic14_hasInterrupt = 1;
2939 #if 0  
2940                 if (!inExcludeList("acc"))              
2941                         pic14_emitcode ("push","acc");  
2942                 if (!inExcludeList("b"))
2943                         pic14_emitcode ("push","b");
2944                 if (!inExcludeList("dpl"))
2945                         pic14_emitcode ("push","dpl");
2946                 if (!inExcludeList("dph"))
2947                         pic14_emitcode ("push","dph");
2948                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
2949                 {
2950                         pic14_emitcode ("push", "dpx");
2951                         /* Make sure we're using standard DPTR */
2952                         pic14_emitcode ("push", "dps");
2953                         pic14_emitcode ("mov", "dps, #0x00");
2954                         if (options.stack10bit)
2955                         { 
2956                                 /* This ISR could conceivably use DPTR2. Better save it. */
2957                                 pic14_emitcode ("push", "dpl1");
2958                                 pic14_emitcode ("push", "dph1");
2959                                 pic14_emitcode ("push", "dpx1");
2960                         }
2961                 }
2962                 /* if this isr has no bank i.e. is going to
2963                 run with bank 0 , then we need to save more
2964                 registers :-) */
2965                 if (!FUNC_REGBANK(sym->type)) {
2966                         
2967                 /* if this function does not call any other
2968                 function then we can be economical and
2969                         save only those registers that are used */
2970                         if (! IFFUNC_HASFCALL(sym->type)) {
2971                                 int i;
2972                                 
2973                                 /* if any registers used */
2974                                 if (sym->regsUsed) {
2975                                         /* save the registers used */
2976                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2977                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2978                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2979                                                         pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
2980                                         }
2981                                 }
2982                                 
2983                         } else {
2984                         /* this function has    a function call cannot
2985                         determines register usage so we will have the
2986                                 entire bank */
2987                                 saverbank(0,ic,FALSE);
2988                         }       
2989                 }
2990 #endif
2991         } else {
2992         /* if callee-save to be used for this function
2993                 then save the registers being used in this function */
2994                 if (IFFUNC_CALLEESAVES(sym->type)) {
2995                         int i;
2996                         
2997                         /* if any registers used */
2998                         if (sym->regsUsed) {
2999                                 /* save the registers used */
3000                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3001                                         if (bitVectBitValue(sym->regsUsed,i) ||
3002                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) ) {
3003                                                 //pic14_emitcode("push","%s",pic14_regWithIdx(i)->dname);
3004                                                 _G.nRegsSaved++;
3005                                         }
3006                                 }
3007                         }
3008                 }
3009         }
3010         
3011         /* set the register bank to the desired value */
3012         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type)) {
3013                 pic14_emitcode("push","psw");
3014                 pic14_emitcode("mov","psw,#0x%02x",(FUNC_REGBANK(sym->type) << 3)&0x00ff);       
3015         }
3016         
3017         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3018                 
3019                 if (options.useXstack) {
3020                         pic14_emitcode("mov","r0,%s",spname);
3021                         pic14_emitcode("mov","a,_bp");
3022                         pic14_emitcode("movx","@r0,a");
3023                         pic14_emitcode("inc","%s",spname);
3024                 }
3025                 else
3026                 {
3027                         /* set up the stack */
3028                         pic14_emitcode ("push","_bp");   /* save the callers stack      */
3029                 }
3030                 pic14_emitcode ("mov","_bp,%s",spname);
3031         }
3032         
3033         /* adjust the stack for the function */
3034         if (sym->stack) {
3035                 
3036                 int i = sym->stack;
3037                 if (i > 256 ) 
3038                         werror(W_STACK_OVERFLOW,sym->name);
3039                 
3040                 if (i > 3 && sym->recvSize < 4) {                
3041                         
3042                         pic14_emitcode ("mov","a,sp");
3043                         pic14_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3044                         pic14_emitcode ("mov","sp,a");
3045                         
3046                 }
3047                 else
3048                         while(i--)
3049                                 pic14_emitcode("inc","sp");
3050         }
3051         
3052         if (sym->xstack) {
3053                 
3054                 pic14_emitcode ("mov","a,_spx");
3055                 pic14_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3056                 pic14_emitcode ("mov","_spx,a");
3057         }
3058         
3059 }
3060
3061 /*-----------------------------------------------------------------*/
3062 /* genEndFunction - generates epilogue for functions                       */
3063 /*-----------------------------------------------------------------*/
3064 static void genEndFunction (iCode *ic)
3065 {
3066         symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3067         
3068         FENTRY;
3069
3070         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3071         
3072         if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3073         {
3074                 pic14_emitcode ("mov","%s,_bp",spname);
3075         }
3076         
3077         /* if use external stack but some variables were
3078         added to the local stack then decrement the
3079         local stack */
3080         if (options.useXstack && sym->stack) {    
3081                 pic14_emitcode("mov","a,sp");
3082                 pic14_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3083                 pic14_emitcode("mov","sp,a");
3084         }
3085         
3086         
3087         if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3088                 if (options.useXstack) {
3089                         pic14_emitcode("mov","r0,%s",spname);
3090                         pic14_emitcode("movx","a,@r0");
3091                         pic14_emitcode("mov","_bp,a");
3092                         pic14_emitcode("dec","%s",spname);
3093                 }
3094                 else
3095                 {
3096                         pic14_emitcode ("pop","_bp");
3097                 }
3098         }
3099         
3100         /* restore the register bank    */        
3101         if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3102                 pic14_emitcode ("pop","psw");
3103         
3104         if (IFFUNC_ISISR(sym->type)) {
3105                 
3106                 /* now we need to restore the registers */
3107                 /* if this isr has no bank i.e. is going to
3108                 run with bank 0 , then we need to save more
3109 registers :-) */
3110                 if (!FUNC_REGBANK(sym->type)) {
3111                         
3112                 /* if this function does not call any other
3113                 function then we can be economical and
3114                         save only those registers that are used */
3115                         if (! IFFUNC_HASFCALL(sym->type)) {
3116                                 int i;
3117                                 
3118                                 /* if any registers used */
3119                                 if (sym->regsUsed) {
3120                                         /* save the registers used */
3121                                         for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3122                                                 if (bitVectBitValue(sym->regsUsed,i) ||
3123                                                         (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3124                                                         pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3125                                         }
3126                                 }
3127                                 
3128                         } else {
3129                         /* this function has    a function call cannot
3130                         determines register usage so we will have the
3131                                 entire bank */
3132                                 unsaverbank(0,ic,FALSE);
3133                         }       
3134                 }
3135 #if 0
3136                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3137                 {
3138                         if (options.stack10bit)
3139                         {
3140                                 pic14_emitcode ("pop", "dpx1");
3141                                 pic14_emitcode ("pop", "dph1");
3142                                 pic14_emitcode ("pop", "dpl1");
3143                         } 
3144                         pic14_emitcode ("pop", "dps");
3145                         pic14_emitcode ("pop", "dpx");
3146                 }
3147                 if (!inExcludeList("dph"))
3148                         pic14_emitcode ("pop","dph");
3149                 if (!inExcludeList("dpl"))
3150                         pic14_emitcode ("pop","dpl");
3151                 if (!inExcludeList("b"))
3152                         pic14_emitcode ("pop","b");
3153                 if (!inExcludeList("acc"))
3154                         pic14_emitcode ("pop","acc");
3155                 
3156                 if (IFFUNC_ISCRITICAL(sym->type))
3157                         pic14_emitcode("setb","ea");
3158 #endif
3159                 
3160                 /* if debug then send end of function */
3161                 /*      if (options.debug && currFunc) { */
3162                 if (currFunc) {
3163                         debugFile->writeEndFunction (currFunc, ic, 1);
3164                 }
3165                 
3166                 pic14_emitcode ("reti","");
3167                 emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
3168                 emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
3169                 emitpcode(POC_CLRF,   popCopyReg(&pc_status));
3170                 emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
3171                 emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
3172                 emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
3173                 emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave));
3174                 addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1));
3175                 emitpcodeNULLop(POC_RETFIE);
3176         }
3177         else {
3178                 if (IFFUNC_ISCRITICAL(sym->type))
3179                         pic14_emitcode("setb","ea");
3180                 
3181                 if (IFFUNC_CALLEESAVES(sym->type)) {
3182                         int i;
3183                         
3184                         /* if any registers used */
3185                         if (sym->regsUsed) {
3186                                 /* save the registers used */
3187                                 for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3188                                         if (bitVectBitValue(sym->regsUsed,i) ||
3189                                                 (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3190                                                 pic14_emitcode("pop","junk");//"%s",pic14_regWithIdx(i)->dname);
3191                                 }
3192                         }
3193                         
3194                 }
3195                 
3196                 /* if debug then send end of function */
3197                 if (currFunc) {
3198                         debugFile->writeEndFunction (currFunc, ic, 1);
3199                 }
3200                 
3201                 pic14_emitcode ("return","");
3202                 emitpcodeNULLop(POC_RETURN);
3203                 
3204                 /* Mark the end of a function */
3205                 addpCode2pBlock(pb,newpCodeFunction(NULL,NULL,0));
3206         }
3207         
3208 }
3209
3210 /*-----------------------------------------------------------------*/
3211 /* genRet - generate code for return statement                                     */
3212 /*-----------------------------------------------------------------*/
3213 static void genRet (iCode *ic)
3214 {
3215         int size,offset = 0;
3216         
3217         FENTRY;
3218
3219         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3220         /* if we have no return value then
3221         just generate the "ret" */
3222         if (!IC_LEFT(ic)) 
3223                 goto jumpret;           
3224         
3225                 /* we have something to return then
3226         move the return value into place */
3227         aopOp(IC_LEFT(ic),ic,FALSE);
3228         size = AOP_SIZE(IC_LEFT(ic));
3229
3230         for (offset = 0; offset < size; offset++)
3231         {
3232                 pass_argument (IC_LEFT(ic), offset, size - 1 - offset);
3233         }
3234         
3235         freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3236         
3237 jumpret:
3238         /* generate a jump to the return label
3239         if the next is not the return statement */
3240         if (!(ic->next && ic->next->op == LABEL &&
3241                 IC_LABEL(ic->next) == returnLabel)) {
3242                 
3243                 emitpcode(POC_GOTO,popGetLabel(returnLabel->key));
3244         }
3245         
3246 }
3247
3248 /*-----------------------------------------------------------------*/
3249 /* genLabel - generates a label                                                                    */
3250 /*-----------------------------------------------------------------*/
3251 static void genLabel (iCode *ic)
3252 {
3253         FENTRY;
3254
3255         /* special case never generate */
3256         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3257         if (IC_LABEL(ic) == entryLabel)
3258                 return ;
3259         
3260         emitpLabel(IC_LABEL(ic)->key);
3261         pic14_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3262 }
3263
3264 /*-----------------------------------------------------------------*/
3265 /* genGoto - generates a goto                                                                      */
3266 /*-----------------------------------------------------------------*/
3267 //tsd
3268 static void genGoto (iCode *ic)
3269 {
3270         FENTRY;
3271
3272         emitpcode(POC_GOTO,popGetLabel(IC_LABEL(ic)->key));
3273         pic14_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3274 }
3275
3276
3277 /*-----------------------------------------------------------------*/
3278 /* genMultbits :- multiplication of bits                                                   */
3279 /*-----------------------------------------------------------------*/
3280 static void genMultbits (operand *left, 
3281                                                  operand *right, 
3282                                                  operand *result)
3283 {
3284         FENTRY;
3285         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3286         
3287         if(!pic14_sameRegs(AOP(result),AOP(right)))
3288                 emitpcode(POC_BSF,      popGet(AOP(result),0));
3289         
3290         emitpcode(POC_BTFSC,popGet(AOP(right),0));
3291         emitpcode(POC_BTFSS,popGet(AOP(left),0));
3292         emitpcode(POC_BCF,  popGet(AOP(result),0));
3293         
3294 }
3295
3296
3297 /*-----------------------------------------------------------------*/
3298 /* genMultOneByte : 8 bit multiplication & division                        */
3299 /*-----------------------------------------------------------------*/
3300 static void genMultOneByte (operand *left,
3301                                                         operand *right,
3302                                                         operand *result)
3303 {
3304         char *func[] = { NULL, "__mulchar", "__mulint", NULL, "__mullong" };
3305         
3306         // symbol *lbl ;
3307         int size,offset,i;
3308         
3309         
3310         FENTRY;
3311         
3312         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3313         DEBUGpic14_AopType(__LINE__,left,right,result);
3314         DEBUGpic14_AopTypeSign(__LINE__,left,right,result);
3315         
3316         /* (if two literals, the value is computed before) */
3317         /* if one literal, literal on the right */
3318         if (AOP_TYPE(left) == AOP_LIT){
3319                 operand *t = right;
3320                 right = left;
3321                 left = t;
3322         }
3323
3324         assert (AOP_SIZE(left) == AOP_SIZE(right));
3325         
3326         size = min(AOP_SIZE(result),AOP_SIZE(left));
3327         offset = Gstack_base_addr - (2*size - 1);
3328
3329         /* pass right operand as argument */
3330         for (i=0; i < size; i++)
3331         {
3332                 mov2w (AOP(right), i);
3333                 emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3334         } // for
3335         
3336         /* pass left operand as argument */
3337         for (i=0; i < size; i++)
3338         {
3339                 mov2w (AOP(left), i);
3340                 if (i != size-1) emitpcode(POC_MOVWF, popRegFromIdx (++offset));
3341         } // for
3342         assert (offset == Gstack_base_addr);
3343         
3344         /* call library routine */
3345         assert (size > 0 && size <= 4);
3346         call_libraryfunc (func[size]);
3347         
3348         /* assign result */
3349         movwf (AOP(result), size-1);
3350         for (i=0; i < size - 1; i++)
3351         {
3352                 emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr - i));
3353                 movwf (AOP(result), size - 2 - i);
3354         } // for
3355
3356         /* now (zero-/sign) extend the result to its size */
3357         addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(result)));
3358 }
3359
3360 /*-----------------------------------------------------------------*/
3361 /* genMult - generates code for multiplication                                     */
3362 /*-----------------------------------------------------------------*/
3363 static void genMult (iCode *ic)
3364 {
3365         operand *left = IC_LEFT(ic);
3366         operand *right = IC_RIGHT(ic);
3367         operand *result= IC_RESULT(ic); 
3368         
3369         FENTRY;
3370
3371         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3372         /* assign the amsops */
3373         aopOp (left,ic,FALSE);
3374         aopOp (right,ic,FALSE);
3375         aopOp (result,ic,TRUE);
3376         
3377         DEBUGpic14_AopType(__LINE__,left,right,result);
3378         
3379         /* special cases first */
3380         /* both are bits */
3381         if (AOP_TYPE(left) == AOP_CRY &&
3382                 AOP_TYPE(right)== AOP_CRY) {
3383                 genMultbits(left,right,result);
3384                 goto release ;
3385         }
3386         
3387         /* if both are of size == 1 */
3388         if (AOP_SIZE(left) == 1 &&
3389                 AOP_SIZE(right) == 1 ) {
3390                 genMultOneByte(left,right,result);
3391                 goto release ;
3392         }
3393         
3394         /* should have been converted to function call */
3395         assert(0) ;
3396         
3397 release :
3398         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3399         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3400         freeAsmop(result,NULL,ic,TRUE); 
3401 }
3402
3403 /*-----------------------------------------------------------------*/
3404 /* genDivbits :- division of bits                                                                  */
3405 /*-----------------------------------------------------------------*/
3406 static void genDivbits (operand *left, 
3407                                                 operand *right, 
3408                                                 operand *result)
3409 {
3410         
3411         char *l;
3412         
3413         FENTRY;
3414
3415         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3416         /* the result must be bit */      
3417         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3418         l = aopGet(AOP(left),0,FALSE,FALSE);
3419         
3420         MOVA(l);          
3421         
3422         pic14_emitcode("div","ab");
3423         pic14_emitcode("rrc","a");
3424         aopPut(AOP(result),"c",0);
3425 }
3426
3427 /*-----------------------------------------------------------------*/
3428 /* genDivOneByte : 8 bit division                                                                  */
3429 /*-----------------------------------------------------------------*/
3430 static void genDivOneByte (operand *left,
3431                                                    operand *right,
3432                                                    operand *result)
3433 {
3434         int size;
3435         
3436         FENTRY;
3437         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3438         
3439         assert (AOP_SIZE(result) == 1);
3440         assert (AOP_SIZE(right) == 1);
3441         assert (AOP_SIZE(left) == 1);
3442
3443         size = min(AOP_SIZE(result),AOP_SIZE(left));
3444
3445         if (AOP_TYPE(right) == AOP_LIT)
3446         {
3447                 /* XXX: might add specialized code */
3448         }
3449
3450         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3451         {
3452                 /* unsigned division */
3453         #if 1
3454                 mov2w(AOP(right),0);
3455                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3456                 mov2w(AOP(left),0);
3457                 call_libraryfunc("__divuchar");
3458                 movwf(AOP(result),0);
3459         #else
3460                 pCodeOp *temp;
3461                 symbol *lbl;
3462
3463                 temp = popGetTempReg();
3464                 lbl = newiTempLabel(NULL);
3465                 
3466                 /* XXX: improve this naive approach:
3467                    [result] = [a] / [b]
3468                         ::= [result] = 0; while ([a] > [b]) do [a] -= [b]; [result]++ done
3469
3470                    In PIC assembler:
3471                    movf  left,W
3472                    movwf temp           // temp <-- left
3473                    movf  right,W        // W <-- right
3474                    clrf  result
3475                    label1:
3476                    incf  result
3477                    subwf temp,F         // temp <-- temp - W
3478                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if temp < W
3479                    goto  label1
3480                    decf result          // we just subtract once too often
3481                  */
3482
3483                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3484                 /* We need 1..128 iterations of the loop body (`4 / 5' .. `255 / 2'). */
3485                 
3486                 mov2w(AOP(left),0);
3487                 emitpcode(POC_MOVWF, temp);
3488                 mov2w(AOP(right),0);
3489                 emitpcode(POC_CLRF, popGet(AOP(result),0));
3490
3491                 emitpLabel(lbl->key);
3492                 emitpcode(POC_INCF, popGet(AOP(result),0));
3493                 emitpcode(POC_SUBWF, temp);
3494                 emitSKPNC;
3495                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3496                 emitpcode(POC_DECF, popGet(AOP(result),0));
3497         #endif
3498         }
3499         else
3500         {
3501                 /* signed division */
3502                 mov2w(AOP(right),0);
3503                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3504                 mov2w(AOP(left),0);
3505                 call_libraryfunc("__divschar");
3506                 movwf(AOP(result),0);
3507         }
3508
3509         /* now performed the signed/unsigned division -- extend result */
3510         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3511 }
3512
3513 /*-----------------------------------------------------------------*/
3514 /* genDiv - generates code for division                            */
3515 /*-----------------------------------------------------------------*/
3516 static void genDiv (iCode *ic)
3517 {
3518         operand *left = IC_LEFT(ic);
3519         operand *right = IC_RIGHT(ic);
3520         operand *result= IC_RESULT(ic); 
3521         
3522         FENTRY;
3523         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3524         /* assign the amsops */
3525         aopOp (left,ic,FALSE);
3526         aopOp (right,ic,FALSE);
3527         aopOp (result,ic,TRUE);
3528         
3529         /* special cases first */
3530         /* both are bits */
3531         if (AOP_TYPE(left) == AOP_CRY &&
3532                 AOP_TYPE(right)== AOP_CRY) {
3533                 genDivbits(left,right,result);
3534                 goto release ;
3535         }
3536         
3537         /* if both are of size == 1 */
3538         if (AOP_SIZE(left) == 1 &&
3539                 AOP_SIZE(right) == 1 ) {
3540                 genDivOneByte(left,right,result);
3541                 goto release ;
3542         }
3543         
3544         /* should have been converted to function call */
3545         assert(0);
3546 release :
3547         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3548         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3549         freeAsmop(result,NULL,ic,TRUE); 
3550 }
3551
3552 /*-----------------------------------------------------------------*/
3553 /* genModbits :- modulus of bits                                                                   */
3554 /*-----------------------------------------------------------------*/
3555 static void genModbits (operand *left, 
3556                                                 operand *right, 
3557                                                 operand *result)
3558 {
3559         
3560         char *l;
3561         
3562         FENTRY;
3563         /* the result must be bit */      
3564         pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
3565         l = aopGet(AOP(left),0,FALSE,FALSE);
3566         
3567         MOVA(l);
3568         
3569         pic14_emitcode("div","ab");
3570         pic14_emitcode("mov","a,b");
3571         pic14_emitcode("rrc","a");
3572         aopPut(AOP(result),"c",0);
3573 }
3574
3575 /*-----------------------------------------------------------------*/
3576 /* genModOneByte : 8 bit modulus                                                                   */
3577 /*-----------------------------------------------------------------*/
3578 static void genModOneByte (operand *left,
3579                                                    operand *right,
3580                                                    operand *result)
3581 {
3582         int size;
3583         
3584         FENTRY;
3585         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3586         
3587         assert (AOP_SIZE(result) == 1);
3588         assert (AOP_SIZE(right) == 1);
3589         assert (AOP_SIZE(left) == 1);
3590
3591         size = min(AOP_SIZE(result),AOP_SIZE(left));
3592
3593         if (AOP_TYPE(right) == AOP_LIT)
3594         {
3595                 /* XXX: might add specialized code */
3596         }
3597
3598         if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
3599         {
3600                 /* unsigned division */
3601         #if 1
3602                 mov2w(AOP(right),0);
3603                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3604                 mov2w(AOP(left),0);
3605                 call_libraryfunc("__moduchar");
3606                 movwf(AOP(result),0);
3607         #else
3608                 pCodeOp *temp;
3609                 symbol *lbl;
3610
3611                 lbl = newiTempLabel(NULL);
3612                 
3613                 assert(!pic14_sameRegs(AOP(right),AOP(result)));
3614
3615                 /* XXX: improve this naive approach:
3616                    [result] = [a] % [b]
3617                         ::= [result] = [a]; while ([result] > [b]) do [result] -= [b]; done
3618
3619                    In PIC assembler:
3620                    movf  left,W
3621                    movwf result         // result <-- left
3622                    movf  right,W        // W <-- right
3623                    label1:
3624                    subwf result,F       // result <-- result - W
3625                    skipNC               // subwf clears CARRY (i.e. sets BORROW) if result < W
3626                    goto  label1
3627                    addwf result, F      // we just subtract once too often
3628                  */
3629
3630                 /* XXX: This loops endlessly on DIVIDE BY ZERO */
3631                 /* We need 1..128 iterations of the loop body (`4 % 5' .. `255 % 2'). */
3632                 
3633                 if (!pic14_sameRegs(AOP(left), AOP(result)))
3634                 {
3635                         mov2w(AOP(left),0);
3636                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
3637                 }
3638                 mov2w(AOP(right),0);
3639
3640                 emitpLabel(lbl->key);
3641                 emitpcode(POC_SUBWF, popGet(AOP(result),0));
3642                 emitSKPNC;
3643                 emitpcode(POC_GOTO, popGetLabel(lbl->key));
3644                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
3645         #endif
3646         }
3647         else
3648         {
3649                 /* signed division */
3650                 mov2w(AOP(right),0);
3651                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
3652                 mov2w(AOP(left),0);
3653                 call_libraryfunc("__modschar");
3654                 movwf(AOP(result),0);
3655         }
3656
3657         /* now we performed the signed/unsigned modulus -- extend result */
3658         addSign(result, 1, !SPEC_USIGN(operandType(result)));
3659 }
3660
3661 /*-----------------------------------------------------------------*/
3662 /* genMod - generates code for division                                                    */
3663 /*-----------------------------------------------------------------*/
3664 static void genMod (iCode *ic)
3665 {
3666         operand *left = IC_LEFT(ic);
3667         operand *right = IC_RIGHT(ic);
3668         operand *result= IC_RESULT(ic);  
3669         
3670         FENTRY;
3671         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3672         /* assign the amsops */
3673         aopOp (left,ic,FALSE);
3674         aopOp (right,ic,FALSE);
3675         aopOp (result,ic,TRUE);
3676         
3677         /* special cases first */
3678         /* both are bits */
3679         if (AOP_TYPE(left) == AOP_CRY &&
3680                 AOP_TYPE(right)== AOP_CRY) {
3681                 genModbits(left,right,result);
3682                 goto release ;
3683         }
3684         
3685         /* if both are of size == 1 */
3686         if (AOP_SIZE(left) == 1 &&
3687                 AOP_SIZE(right) == 1 ) {
3688                 genModOneByte(left,right,result);
3689                 goto release ;
3690         }
3691         
3692         /* should have been converted to function call */
3693         assert(0);
3694         
3695 release :
3696         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3697         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3698         freeAsmop(result,NULL,ic,TRUE); 
3699 }
3700
3701 /*-----------------------------------------------------------------*/
3702 /* genIfxJump :- will create a jump depending on the ifx                   */
3703 /*-----------------------------------------------------------------*/
3704 /*
3705 note: May need to add parameter to indicate when a variable is in bit space.
3706 */
3707 static void genIfxJump (iCode *ic, char *jval)
3708 {
3709         
3710         FENTRY;
3711         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3712         /* if true label then we jump if condition
3713         supplied is true */
3714         if ( IC_TRUE(ic) ) {
3715                 
3716                 if(strcmp(jval,"a") == 0)
3717                         emitSKPZ;
3718                 else if (strcmp(jval,"c") == 0)
3719                         emitSKPC;
3720                 else {
3721                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3722                         emitpcode(POC_BTFSC,    newpCodeOpBit(jval,-1,1));
3723                 }
3724                 
3725                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ic)->key));
3726                 pic14_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3727                 
3728         }
3729         else {
3730                 /* false label is present */
3731                 if(strcmp(jval,"a") == 0)
3732                         emitSKPNZ;
3733                 else if (strcmp(jval,"c") == 0)
3734                         emitSKPNC;
3735                 else {
3736                         DEBUGpic14_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval); 
3737                         emitpcode(POC_BTFSS,    newpCodeOpBit(jval,-1,1));
3738                 }
3739                 
3740                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ic)->key));
3741                 pic14_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3742                 
3743         }
3744         
3745         
3746         /* mark the icode as generated */
3747         ic->generated = 1;
3748 }
3749
3750 #if 0
3751 /*-----------------------------------------------------------------*/
3752 /* genSkip                                                                                                                 */
3753 /*-----------------------------------------------------------------*/
3754 static void genSkip(iCode *ifx,int status_bit)
3755 {
3756         FENTRY;
3757         if(!ifx)
3758                 return;
3759         
3760         if ( IC_TRUE(ifx) ) {
3761                 switch(status_bit) {
3762                 case 'z':
3763                         emitSKPNZ;
3764                         break;
3765                         
3766                 case 'c':
3767                         emitSKPNC;
3768                         break;
3769                         
3770                 case 'd':
3771                         emitSKPDC;
3772                         break;
3773                         
3774                 }
3775                 
3776                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3777                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3778                 
3779         } else {
3780                 
3781                 switch(status_bit) {
3782                         
3783                 case 'z':
3784                         emitSKPZ;
3785                         break;
3786                         
3787                 case 'c':
3788                         emitSKPC;
3789                         break;
3790                         
3791                 case 'd':
3792                         emitSKPDC;
3793                         break;
3794                 }
3795                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3796                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3797                 
3798         }
3799         
3800 }
3801 #endif
3802
3803 /*-----------------------------------------------------------------*/
3804 /* genSkipc                                                                                                        */
3805 /*-----------------------------------------------------------------*/
3806 static void genSkipc(resolvedIfx *rifx)
3807 {
3808         FENTRY;
3809         if(!rifx)
3810                 return;
3811         
3812         if(rifx->condition)
3813                 emitSKPNC;
3814         else
3815                 emitSKPC;
3816         
3817         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3818         emitpComment ("%s:%u: created from rifx:%p", __FUNCTION__, __LINE__, rifx);
3819         rifx->generated = 1;
3820 }
3821
3822 #if 0
3823 /*-----------------------------------------------------------------*/
3824 /* genSkipz2                                                                                                       */
3825 /*-----------------------------------------------------------------*/
3826 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3827 {
3828         FENTRY;
3829         if(!rifx)
3830                 return;
3831         
3832         if( (rifx->condition ^ invert_condition) & 1)
3833                 emitSKPZ;
3834         else
3835                 emitSKPNZ;
3836         
3837         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3838         rifx->generated = 1;
3839 }
3840 #endif
3841
3842 #if 0
3843 /*-----------------------------------------------------------------*/
3844 /* genSkipz                                                        */
3845 /*-----------------------------------------------------------------*/
3846 static void genSkipz(iCode *ifx, int condition)
3847 {
3848         FENTRY;
3849         assert (ifx != NULL);
3850         
3851         if(condition)
3852                 emitSKPNZ;
3853         else
3854                 emitSKPZ;
3855         
3856         if ( IC_TRUE(ifx) )
3857                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
3858         else
3859                 emitpcode(POC_GOTO,popGetLabel(IC_FALSE(ifx)->key));
3860         
3861         if ( IC_TRUE(ifx) )
3862                 pic14_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3863         else
3864                 pic14_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3865         
3866 }
3867 #endif
3868
3869 #if 0
3870 /*-----------------------------------------------------------------*/
3871 /* genSkipCond                                                     */
3872 /*-----------------------------------------------------------------*/
3873 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3874 {
3875         FENTRY;
3876         if(!rifx)
3877                 return;
3878         
3879         if(rifx->condition)
3880                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3881         else
3882                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3883         
3884         
3885         emitpcode(POC_GOTO,popGetLabel(rifx->lbl->key));
3886         rifx->generated = 1;
3887 }
3888 #endif
3889
3890 #if 0
3891 /*-----------------------------------------------------------------*/
3892 /* genChkZeroes :- greater or less than comparison                 */
3893 /*     For each byte in a literal that is zero, inclusive or the   */
3894 /*     the corresponding byte in the operand with W                */
3895 /*     returns true if any of the bytes are zero                   */
3896 /*-----------------------------------------------------------------*/
3897 static int genChkZeroes(operand *op, int lit,  int size)
3898 {
3899         
3900         int i;
3901         int flag =1;
3902         
3903         while(size--) {
3904                 i = (lit >> (size*8)) & 0xff;
3905                 
3906                 if(i==0) {
3907                         if(flag) 
3908                                 emitpcode(POC_MOVFW, popGet(AOP(op),size));
3909                         else
3910                                 emitpcode(POC_IORFW, popGet(AOP(op),size));
3911                         flag = 0;
3912                 }
3913         }
3914         
3915         return (flag==0);
3916 }
3917 #endif
3918
3919
3920 #define isAOP_REGlike(x)  (AOP_TYPE(x) == AOP_REG || AOP_TYPE(x) == AOP_DIR || AOP_TYPE(x) == AOP_PCODE)
3921 #define isAOP_LIT(x)      (AOP_TYPE(x) == AOP_LIT)
3922 #define DEBUGpc           emitpComment
3923
3924 /*-----------------------------------------------------------------*/
3925 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
3926 /*                  aop (if it's NOT a literal) or from lit (if    */
3927 /*                  aop is a literal)                              */
3928 /*-----------------------------------------------------------------*/
3929 void pic14_mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
3930   if (aop->type == AOP_LIT) {
3931     emitpcode (POC_MOVLW, popGetLit((lit >> (offset*8)) & 0x00FF));
3932   } else {
3933     emitpcode (POC_MOVFW, popGet (aop, offset));
3934   }
3935 }
3936
3937 /* genCmp performs a left < right comparison, stores
3938  * the outcome in result (if != NULL) and generates
3939  * control flow code for the ifx (if != NULL).
3940  *
3941  * This version leaves in sequences like
3942  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
3943  * which should be optmized by the peephole
3944  * optimizer - RN 2005-01-01 */
3945 static void genCmp (operand *left,operand *right,
3946                     operand *result, iCode *ifx, int sign)
3947 {
3948   resolvedIfx rIfx;
3949   int size;
3950   int offs;
3951   symbol *templbl;
3952   operand *dummy;
3953   unsigned long lit;
3954   unsigned long mask;
3955   int performedLt;
3956   int invert_result = 0;
3957
3958   FENTRY;
3959   
3960   assert (AOP_SIZE(left) == AOP_SIZE(right));
3961   assert (left && right);
3962
3963   size = AOP_SIZE(right) - 1;
3964   mask = (0x100UL << (size*8)) - 1;
3965   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
3966   performedLt = 1;
3967   templbl = NULL;
3968   lit = 0;
3969   
3970   resolveIfx (&rIfx, ifx);
3971
3972   /**********************************************************************
3973    * handle bits - bit compares are promoted to int compares seemingly! *
3974    **********************************************************************/
3975 #if 0
3976   // THIS IS COMPLETELY UNTESTED!
3977   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
3978     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
3979     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
3980     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
3981
3982     emitSETC;
3983     // 1 < {0,1} is false --> clear C by skipping the next instruction
3984     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
3985     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
3986     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
3987     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
3988     emitCLRC; // only skipped for left=0 && right=1
3989
3990     goto correct_result_in_carry;
3991   } // if
3992 #endif
3993
3994   /*************************************************
3995    * make sure that left is register (or the like) *
3996    *************************************************/
3997   if (!isAOP_REGlike(left)) {
3998     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
3999     assert (isAOP_LIT(left));
4000     assert (isAOP_REGlike(right));
4001     // swap left and right
4002     // left < right <==> right > left <==> (right >= left + 1)
4003     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4004
4005     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4006       // MAXVALUE < right? always false
4007       if (performedLt) emitCLRC; else emitSETC;
4008       goto correct_result_in_carry;
4009     } // if
4010
4011     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4012     // that's why we handled it above.
4013     lit++;
4014
4015     dummy = left;
4016     left = right;
4017     right = dummy;
4018
4019     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4020   } else if (isAOP_LIT(right)) {
4021     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4022   } // if
4023
4024   assert (isAOP_REGlike(left)); // left must be register or the like
4025   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4026
4027   /*************************************************
4028    * special cases go here                         *
4029    *************************************************/
4030
4031   if (isAOP_LIT(right)) {
4032     if (!sign) {
4033       // unsigned comparison to a literal
4034       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4035       if (lit == 0) {
4036         // unsigned left < 0? always false
4037         if (performedLt) emitCLRC; else emitSETC;
4038         goto correct_result_in_carry;
4039       }
4040     } else {
4041       // signed comparison to a literal
4042       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4043       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4044         // signed left < 0x80000000? always false
4045         if (performedLt) emitCLRC; else emitSETC;
4046         goto correct_result_in_carry;
4047       } else if (lit == 0) {
4048         // compare left < 0; set CARRY if SIGNBIT(left) is set
4049         if (performedLt) emitSETC; else emitCLRC;
4050         emitpcode (POC_BTFSS, newpCodeOpBit (aopGet (AOP(left), size, FALSE, FALSE), 7, 0));
4051         if (performedLt) emitCLRC; else emitSETC;
4052         goto correct_result_in_carry;
4053       }
4054     } // if (!sign)
4055   } // right is literal
4056
4057   /*************************************************
4058    * perform a general case comparison             *
4059    * make sure we get CARRY==1 <==> left >= right  *
4060    *************************************************/
4061   // compare most significant bytes
4062   //DEBUGpc ("comparing bytes at offset %d", size);
4063   if (!sign) {
4064     // unsigned comparison
4065     pic14_mov2w_regOrLit (AOP(right), lit, size);
4066     emitpcode (POC_SUBFW, popGet (AOP(left), size));
4067   } else {
4068     // signed comparison
4069     // (add 2^n to both operands then perform an unsigned comparison)
4070     if (isAOP_LIT(right)) {
4071       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
4072       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
4073
4074       if (litbyte == 0x80) {
4075         // left >= 0x80 -- always true, but more bytes to come
4076         mov2w (AOP(left), size);
4077         emitpcode (POC_XORLW, popGetLit (0x80)); // set ZERO flag
4078         emitSETC;
4079       } else {
4080         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
4081         mov2w (AOP(left), size);
4082         emitpcode (POC_ADDLW, popGetLit (0x80));
4083         emitpcode (POC_ADDLW, popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
4084       } // if
4085     } else {
4086       pCodeOp *pctemp = popGetTempReg();
4087       mov2w (AOP(left), size);
4088       emitpcode (POC_ADDLW, popGetLit (0x80));
4089       emitpcode (POC_MOVWF, pctemp);
4090       mov2w (AOP(right), size);
4091       emitpcode (POC_ADDLW, popGetLit (0x80));
4092       emitpcode (POC_SUBFW, pctemp);
4093       popReleaseTempReg(pctemp);
4094     }
4095   } // if (!sign)
4096
4097   // compare remaining bytes (treat as unsigned case from above)
4098   templbl = newiTempLabel ( NULL );
4099   offs = size;
4100   while (offs--) {
4101     //DEBUGpc ("comparing bytes at offset %d", offs);
4102     emitSKPZ;
4103     emitpcode (POC_GOTO, popGetLabel (templbl->key));
4104     pic14_mov2w_regOrLit (AOP(right), lit, offs);
4105     emitpcode (POC_SUBFW, popGet (AOP(left), offs));
4106   } // while (offs)
4107   emitpLabel (templbl->key);
4108   goto result_in_carry;
4109
4110 result_in_carry:
4111   
4112   /****************************************************
4113    * now CARRY contains the result of the comparison: *
4114    * SUBWF sets CARRY iff                             *
4115    * F-W >= 0 <==> F >= W <==> !(F < W)               *
4116    * (F=left, W=right)                                *
4117    ****************************************************/
4118
4119   if (performedLt) {
4120     invert_result = 1;
4121     // value will be used in the following genSkipc()
4122     rIfx.condition ^= 1;
4123   } // if
4124
4125 correct_result_in_carry:
4126
4127   // assign result to variable (if neccessary)
4128   if (result && AOP_TYPE(result) != AOP_CRY) {
4129     //DEBUGpc ("assign result");
4130     size = AOP_SIZE(result);
4131     while (size--) {
4132       emitpcode (POC_CLRF, popGet (AOP(result), size));
4133     } // while
4134     if (invert_result) {
4135       emitSKPC;
4136       emitpcode (POC_BSF, newpCodeOpBit (aopGet (AOP(result), 0, FALSE, FALSE), 0, 0));
4137     } else {
4138       emitpcode (POC_RLF, popGet (AOP(result), 0));
4139     }
4140   } // if (result)
4141
4142   // perform conditional jump
4143   if (ifx) {
4144     //DEBUGpc ("generate control flow");
4145     genSkipc (&rIfx);
4146     ifx->generated = 1;
4147   } // if
4148 }
4149
4150
4151 #if 0
4152 /* OLD VERSION -- BUGGY, DO NOT USE */
4153
4154 /*-----------------------------------------------------------------*/
4155 /* genCmp :- greater or less than comparison                       */
4156 /*-----------------------------------------------------------------*/
4157 static void genCmp (operand *left,operand *right,
4158                                         operand *result, iCode *ifx, int sign)
4159 {
4160         int size; //, offset = 0 ;
4161         unsigned long lit = 0L,i = 0;
4162         resolvedIfx rFalseIfx;
4163         //  resolvedIfx rTrueIfx;
4164         symbol *truelbl;
4165
4166         FENTRY;
4167         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4168         /*
4169         if(ifx) {
4170         DEBUGpic14_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4171         DEBUGpic14_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4172         }
4173         */
4174         
4175         resolveIfx(&rFalseIfx,ifx);
4176         truelbl  = newiTempLabel(NULL);
4177         size = max(AOP_SIZE(left),AOP_SIZE(right));
4178         
4179         DEBUGpic14_AopType(__LINE__,left,right,result);
4180         
4181 #define _swapp
4182         
4183         /* if literal is on the right then swap with left */
4184         if ((AOP_TYPE(right) == AOP_LIT)) {
4185                 operand *tmp = right ;
4186                 unsigned long mask = (0x100 << (8*(size-1))) - 1;
4187                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4188 #ifdef _swapp
4189                 
4190                 lit = (lit - 1) & mask;
4191                 right = left;
4192                 left = tmp;
4193                 rFalseIfx.condition ^= 1;
4194 #endif
4195                 
4196         } else if ((AOP_TYPE(left) == AOP_LIT)) {
4197                 lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4198         }
4199         
4200         
4201         //if(IC_TRUE(ifx) == NULL)
4202         /* if left & right are bit variables */
4203         if (AOP_TYPE(left) == AOP_CRY &&
4204                 AOP_TYPE(right) == AOP_CRY ) {
4205                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4206                 pic14_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4207         } else {
4208         /* subtract right from left if at the
4209         end the carry flag is set then we know that
4210                 left is greater than right */
4211                 
4212                 symbol *lbl  = newiTempLabel(NULL);
4213                 
4214 #ifndef _swapp
4215                 if(AOP_TYPE(right) == AOP_LIT) {
4216                         
4217                         //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4218                         
4219                         DEBUGpic14_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4220                         
4221                         /* special cases */
4222                         
4223                         if(lit == 0) {
4224                                 
4225                                 if(sign != 0) 
4226                                         genSkipCond(&rFalseIfx,left,size-1,7);
4227                                 else 
4228                                         /* no need to compare to 0...*/
4229                                         /* NOTE: this is a de-generate compare that most certainly 
4230                                         *       creates some dead code. */
4231                                         emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4232                                 
4233                                 if(ifx) ifx->generated = 1;
4234                                 return;
4235                                 
4236                         }
4237                         size--;
4238                         
4239                         if(size == 0) {
4240                                 //i = (lit >> (size*8)) & 0xff;
4241                                 DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4242                                 
4243                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4244                                 
4245                                 i = ((0-lit) & 0xff);
4246                                 if(sign) {
4247                                         if( i == 0x81) { 
4248                                         /* lit is 0x7f, all signed chars are less than
4249                                                 * this except for 0x7f itself */
4250                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4251                                                 genSkipz2(&rFalseIfx,0);
4252                                         } else {
4253                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4254                                                 emitpcode(POC_ADDLW, popGetLit(i^0x80));
4255                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4256                                         }
4257                                         
4258                                 } else {
4259                                         if(lit == 1) {
4260                                                 genSkipz2(&rFalseIfx,1);
4261                                         } else {
4262                                                 emitpcode(POC_ADDLW, popGetLit(i));
4263                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4264                                         }
4265                                 }
4266                                 
4267                                 if(ifx) ifx->generated = 1;
4268                                 return;
4269                         }
4270                         
4271                         /* chars are out of the way. now do ints and longs */
4272                         
4273                         
4274                         DEBUGpic14_emitcode(";right lit","line = %d",__LINE__);
4275                         
4276                         /* special cases */
4277                         
4278                         if(sign) {
4279                                 
4280                                 if(lit == 0) {
4281                                         genSkipCond(&rFalseIfx,left,size,7);
4282                                         if(ifx) ifx->generated = 1;
4283                                         return;
4284                                 }
4285                                 
4286                                 if(lit <0x100) {
4287                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4288                                         
4289                                         //rFalseIfx.condition ^= 1;
4290                                         //genSkipCond(&rFalseIfx,left,size,7);
4291                                         //rFalseIfx.condition ^= 1;
4292                                         
4293                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4294                                         if(rFalseIfx.condition)
4295                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4296                                         else
4297                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4298                                         
4299                                         emitpcode(POC_MOVLW, popGetLit(0x100-lit));
4300                                         emitpcode(POC_ADDFW, popGet(AOP(left),0));
4301                                         emitpcode(POC_MOVFW, popGet(AOP(left),1));
4302                                         
4303                                         while(size > 1)
4304                                                 emitpcode(POC_IORFW, popGet(AOP(left),size--));
4305                                         
4306                                         if(rFalseIfx.condition) {
4307                                                 emitSKPZ;
4308                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4309                                                 
4310                                         } else {
4311                                                 emitSKPNZ;
4312                                         }
4313                                         
4314                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4315                                         emitpLabel(truelbl->key);
4316                                         if(ifx) ifx->generated = 1;
4317                                         return;
4318                                         
4319                                 }
4320                                 
4321                                 if(size == 1) {
4322                                         
4323                                         if( (lit & 0xff) == 0) {
4324                                                 /* lower byte is zero */
4325                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4326                                                 i = ((lit >> 8) & 0xff) ^0x80;
4327                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4328                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4329                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4330                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4331                                                 
4332                                                 
4333                                                 if(ifx) ifx->generated = 1;
4334                                                 return;
4335                                                 
4336                                         }
4337                                 } else {
4338                                         /* Special cases for signed longs */
4339                                         if( (lit & 0xffffff) == 0) {
4340                                                 /* lower byte is zero */
4341                                                 DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4342                                                 i = ((lit >> 8*3) & 0xff) ^0x80;
4343                                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4344                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4345                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4346                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4347                                                 
4348                                                 
4349                                                 if(ifx) ifx->generated = 1;
4350                                                 return;
4351                                                 
4352                                         }
4353                                         
4354                                 }
4355                                 
4356                                 
4357                                 if(lit & (0x80 << (size*8))) {
4358                                         /* lit is negative */
4359                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4360                                         
4361                                         //genSkipCond(&rFalseIfx,left,size,7);
4362                                         
4363                                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4364                                         
4365                                         if(rFalseIfx.condition)
4366                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4367                                         else
4368                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4369                                         
4370                                         
4371                                 } else {
4372                                         /* lit is positive */
4373                                         DEBUGpic14_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4374                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),size,FALSE,FALSE),7,0));
4375                                         if(rFalseIfx.condition)
4376                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4377                                         else
4378                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4379                                         
4380                                 }
4381                                 
4382                                 /* There are no more special cases, so perform a general compare */
4383                                 
4384                                 emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4385                                 emitpcode(POC_SUBFW, popGet(AOP(left),size));
4386                                 
4387                                 while(size--) {
4388                                         
4389                                         emitpcode(POC_MOVLW, popGetLit((lit >> (size*8)) & 0xff));
4390                                         emitSKPNZ;
4391                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4392                                 }
4393                                 //rFalseIfx.condition ^= 1;
4394                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4395                                 
4396                                 emitpLabel(truelbl->key);
4397                                 
4398                                 if(ifx) ifx->generated = 1;
4399                                 return;
4400                                 
4401                                 
4402                         }
4403
4404
4405                         /* sign is out of the way. So now do an unsigned compare */
4406                         DEBUGpic14_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4407
4408
4409                         /* General case - compare to an unsigned literal on the right.*/
4410
4411                         i = (lit >> (size*8)) & 0xff;
4412                         emitpcode(POC_MOVLW, popGetLit(i));
4413                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4414                         while(size--) {
4415                                 i = (lit >> (size*8)) & 0xff;
4416                                 
4417                                 if(i) {
4418                                         emitpcode(POC_MOVLW, popGetLit(i));
4419                                         emitSKPNZ;
4420                                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4421                                 } else {
4422                                 /* this byte of the lit is zero, 
4423                                         *if it's not the last then OR in the variable */
4424                                         if(size)
4425                                                 emitpcode(POC_IORFW, popGet(AOP(left),size));
4426                                 }
4427                         }
4428
4429
4430                 emitpLabel(lbl->key);
4431                 //if(emitFinalCheck)
4432                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4433                 if(sign)
4434                         emitpLabel(truelbl->key);
4435
4436                 if(ifx) ifx->generated = 1;
4437                 return;
4438
4439
4440                 }
4441 #endif  // _swapp
4442
4443                 if(AOP_TYPE(left) == AOP_LIT) {
4444                         //symbol *lbl = newiTempLabel(NULL);
4445                         
4446                         //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4447                         
4448                         
4449                         DEBUGpic14_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4450                         
4451                         /* Special cases */
4452                         if((lit == 0) && (sign == 0)){
4453                                 
4454                                 size--;
4455                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4456                                 while(size) 
4457                                         emitpcode(POC_IORFW, popGet(AOP(right),--size));
4458                                 
4459                                 genSkipz2(&rFalseIfx,0);
4460                                 if(ifx) ifx->generated = 1;
4461                                 return;
4462                         }
4463                         
4464                         if(size==1) {
4465                                 /* Special cases */
4466                                 lit &= 0xff;
4467                                 if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4468                                         /* degenerate compare can never be true */
4469                                         if(rFalseIfx.condition == 0)
4470                                                 emitpcode(POC_GOTO,popGetLabel(rFalseIfx.lbl->key));
4471                                         
4472                                         if(ifx) ifx->generated = 1;
4473                                         return;
4474                                 }
4475                                 
4476                                 if(sign) {
4477                                         /* signed comparisons to a literal byte */
4478                                         
4479                                         int lp1 = (lit+1) & 0xff;
4480                                         
4481                                         DEBUGpic14_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4482                                         switch (lp1) {
4483                                         case 0:
4484                                                 rFalseIfx.condition ^= 1;
4485                                                 genSkipCond(&rFalseIfx,right,0,7);
4486                                                 break;
4487                                         case 0x7f:
4488                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4489                                                 emitpcode(POC_XORLW, popGetLit(0x7f));
4490                                                 genSkipz2(&rFalseIfx,1);
4491                                                 break;
4492                                         default:
4493                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4494                                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4495                                                 emitpcode(POC_ADDLW, popGetLit(((0-(lit+1)) & 0xff) ^ 0x80));
4496                                                 rFalseIfx.condition ^= 1;
4497                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4498                                                 break;
4499                                         }
4500                                         if(ifx) ifx->generated = 1;
4501                                 } else {
4502                                         /* unsigned comparisons to a literal byte */
4503                                         
4504                                         switch(lit & 0xff ) {
4505                                         case 0:
4506                                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4507                                                 genSkipz2(&rFalseIfx,0);
4508                                                 if(ifx) ifx->generated = 1;
4509                                                 break;
4510                                         case 0x7f:
4511                                                 genSkipCond(&rFalseIfx,right,0,7);
4512                                                 if(ifx) ifx->generated = 1;
4513                                                 break;
4514                                                 
4515                                         default:
4516                                                 emitpcode(POC_MOVLW, popGetLit((lit+1) & 0xff));
4517                                                 emitpcode(POC_SUBFW, popGet(AOP(right),0));
4518                                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4519                                                 rFalseIfx.condition ^= 1;
4520                                                 if (AOP_TYPE(result) == AOP_CRY) {
4521                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4522                                                         if(ifx) ifx->generated = 1;
4523                                                 } else {
4524                                                         DEBUGpic14_emitcode ("; ***","%s  %d RFIfx.cond=%d",__FUNCTION__,__LINE__, rFalseIfx.condition);
4525                                                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4526                                                         emitpcode(POC_RLF, popGet(AOP(result),0));
4527                                                         emitpcode(POC_MOVLW, popGetLit(0x01));
4528                                                         emitpcode(POC_XORWF, popGet(AOP(result),0));
4529                                                 }       
4530                                                 break;
4531                                         }
4532                                 }
4533                                 
4534                                 //goto check_carry;
4535                                 return;
4536                                 
4537                         } else {
4538                                 
4539                                 /* Size is greater than 1 */
4540                                 
4541                                 if(sign) {
4542                                         int lp1 = lit+1;
4543                                         
4544                                         size--;
4545                                         
4546                                         if(lp1 == 0) {
4547                                                 /* this means lit = 0xffffffff, or -1 */
4548                                                 
4549                                                 
4550                                                 DEBUGpic14_emitcode(";left lit = -1","line = %d ",__LINE__);
4551                                                 rFalseIfx.condition ^= 1;
4552                                                 genSkipCond(&rFalseIfx,right,size,7);
4553                                                 if(ifx) ifx->generated = 1;
4554                                                 return;
4555                                         }
4556                                         
4557                                         if(lit == 0) {
4558                                                 int s = size;
4559                                                 
4560                                                 if(rFalseIfx.condition) {
4561                                                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4562                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4563                                                 }
4564                                                 
4565                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4566                                                 while(size--)
4567                                                         emitpcode(POC_IORFW, popGet(AOP(right),size));
4568                                                 
4569                                                 
4570                                                 emitSKPZ;
4571                                                 if(rFalseIfx.condition) {
4572                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4573                                                         emitpLabel(truelbl->key);
4574                                                 }else {
4575                                                         rFalseIfx.condition ^= 1;
4576                                                         genSkipCond(&rFalseIfx,right,s,7);
4577                                                 }
4578                                                 
4579                                                 if(ifx) ifx->generated = 1;
4580                                                 return;
4581                                         }
4582                                         
4583                                         if((size == 1) &&  (0 == (lp1&0xff))) {
4584                                                 /* lower byte of signed word is zero */
4585                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4586                                                 i = ((lp1 >> 8) & 0xff) ^0x80;
4587                                                 emitpcode(POC_MOVFW, popGet(AOP(right),size));
4588                                                 emitpcode(POC_ADDLW, popGetLit( 0x80));
4589                                                 emitpcode(POC_ADDLW, popGetLit(0x100-i));
4590                                                 rFalseIfx.condition ^= 1;
4591                                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4592                                                 
4593                                                 
4594                                                 if(ifx) ifx->generated = 1;
4595                                                 return;
4596                                         }
4597                                         
4598                                         if(lit & (0x80 << (size*8))) {
4599                                                 /* Lit is less than zero */
4600                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4601                                                 //rFalseIfx.condition ^= 1;
4602                                                 //genSkipCond(&rFalseIfx,left,size,7);
4603                                                 //rFalseIfx.condition ^= 1;
4604                                                 emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4605                                                 //emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4606                                                 
4607                                                 if(rFalseIfx.condition)
4608                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4609                                                 else
4610                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4611                                                 
4612                                                 
4613                                         } else {
4614                                                 /* Lit is greater than or equal to zero */
4615                                                 DEBUGpic14_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4616                                                 //rFalseIfx.condition ^= 1;
4617                                                 //genSkipCond(&rFalseIfx,right,size,7);
4618                                                 //rFalseIfx.condition ^= 1;
4619                                                 
4620                                                 //emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4621                                                 //emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4622                                                 
4623                                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),size,FALSE,FALSE),7,0));
4624                                                 if(rFalseIfx.condition)
4625                                                         emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4626                                                 else
4627                                                         emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4628                                                 
4629                                         }
4630                                         
4631                                         
4632                                         emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4633                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4634                                         
4635                                         while(size--) {
4636                                                 
4637                                                 emitpcode(POC_MOVLW, popGetLit((lp1 >> (size*8)) & 0xff));
4638                                                 emitSKPNZ;
4639                                                 emitpcode(POC_SUBFW, popGet(AOP(right),size));
4640                                         }
4641                                         rFalseIfx.condition ^= 1;
4642                                         //rFalseIfx.condition = 1;
4643                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4644                                         
4645                                         emitpLabel(truelbl->key);
4646                                         
4647                                         if(ifx) ifx->generated = 1;
4648                                         return;
4649                                         // end of if (sign)
4650                                 } else {
4651                                         
4652                                         /* compare word or long to an unsigned literal on the right.*/
4653                                         
4654                                         
4655                                         size--;
4656                                         if(lit < 0xff) {
4657                                                 DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4658                                                 switch (lit) {
4659                                                 case 0:
4660                                                         break; /* handled above */
4661                                                 /*
4662                                                 case 0xff:
4663                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4664                                                         while(size--)
4665                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4666                                                         genSkipz2(&rFalseIfx,0);
4667                                                         break;
4668                                                 */
4669                                                 default:
4670                                                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4671                                                         while(--size)
4672                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4673                                                         
4674                                                         emitSKPZ;
4675                                                         if(rFalseIfx.condition)
4676                                                                 emitpcode(POC_GOTO,  popGetLabel(rFalseIfx.lbl->key));
4677                                                         else
4678                                                                 emitpcode(POC_GOTO,  popGetLabel(truelbl->key));
4679                                                         
4680                                                         
4681                                                         emitpcode(POC_MOVLW, popGetLit(lit+1));
4682                                                         emitpcode(POC_SUBFW, popGet(AOP(right),0));
4683                                                         
4684                                                         rFalseIfx.condition ^= 1;
4685                                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4686                                                 }
4687                                                 
4688                                                 emitpLabel(truelbl->key);
4689                                                 
4690                                                 if(ifx) ifx->generated = 1;
4691                                                 return;
4692                                         }
4693                                         
4694                                         
4695                                         lit++;
4696                                         DEBUGpic14_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4697                                         i = (lit >> (size*8)) & 0xff;
4698                                         
4699                                         emitpcode(POC_MOVLW, popGetLit(i));
4700                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4701                                         
4702                                         while(size--) {
4703                                                 i = (lit >> (size*8)) & 0xff;
4704                                                 
4705                                                 if(i) {
4706                                                         emitpcode(POC_MOVLW, popGetLit(i));
4707                                                         emitSKPNZ;
4708                                                         emitpcode(POC_SUBFW, popGet(AOP(right),size));
4709                                                 } else {
4710                                                 /* this byte of the lit is zero, 
4711                                                         *if it's not the last then OR in the variable */
4712                                                         if(size)
4713                                                                 emitpcode(POC_IORFW, popGet(AOP(right),size));
4714                                                 }
4715                                         }
4716                                         
4717                                         
4718                                         emitpLabel(lbl->key);
4719                                         
4720                                         rFalseIfx.condition ^= 1;
4721                                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4722                                 }
4723                                 
4724                                 if(sign)
4725                                         emitpLabel(truelbl->key);
4726                                 if(ifx) ifx->generated = 1;
4727                                 return;
4728                         }
4729                 }
4730                 /* Compare two variables */
4731                 
4732                 DEBUGpic14_emitcode(";sign","%d",sign);
4733                 
4734                 size--;
4735                 if(sign) {
4736                         /* Sigh. thus sucks... */
4737                         if(size) {
4738                                 emitpcode(POC_MOVFW, popGet(AOP(left),size));
4739                                 emitpcode(POC_MOVWF, popRegFromIdx(Gstack_base_addr));
4740                                 emitpcode(POC_MOVLW, popGetLit(0x80));
4741                                 emitpcode(POC_XORWF, popRegFromIdx(Gstack_base_addr));
4742                                 emitpcode(POC_XORFW, popGet(AOP(right),size));
4743                                 emitpcode(POC_SUBFW, popRegFromIdx(Gstack_base_addr));
4744                         } else {
4745                                 /* Signed char comparison */
4746                                 /* Special thanks to Nikolai Golovchenko for this snippet */
4747                                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
4748                                 emitpcode(POC_SUBFW, popGet(AOP(left),0));
4749                                 emitpcode(POC_RRFW,  popGet(AOP(left),0)); /* could be any register */
4750                                 emitpcode(POC_XORFW, popGet(AOP(left),0));
4751                                 emitpcode(POC_XORFW, popGet(AOP(right),0));
4752                                 emitpcode(POC_ADDLW, popGetLit(0x80));
4753                                 
4754                                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4755                                 genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4756                                 
4757                                 if(ifx) ifx->generated = 1;
4758                                 return;
4759                         }
4760                         
4761                 } else {
4762                         
4763                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4764                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4765                 }
4766                 
4767                 
4768                 /* The rest of the bytes of a multi-byte compare */
4769                 while (size) {
4770                         
4771                         emitSKPZ;
4772                         emitpcode(POC_GOTO,  popGetLabel(lbl->key));
4773                         size--;
4774                         
4775                         emitpcode(POC_MOVFW, popGet(AOP(right),size));
4776                         emitpcode(POC_SUBFW, popGet(AOP(left),size));
4777                         
4778                         
4779                 }
4780                 
4781                 emitpLabel(lbl->key);
4782                 
4783                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4784                 if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4785                         (AOP_TYPE(result) == AOP_REG)) {
4786                         emitpcode(POC_CLRF, popGet(AOP(result),0));
4787                         emitpcode(POC_RLF, popGet(AOP(result),0));
4788                 } else {
4789                         genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4790                 }       
4791                 //genSkipc(&rFalseIfx); assert ( !"genSkipc should have inverse logic" );
4792                 if(ifx) ifx->generated = 1;
4793                 
4794                 return;
4795                 
4796         }
4797         
4798         // check_carry:
4799         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4800                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4801                 pic14_outBitC(result);
4802         } else {
4803                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4804                 /* if the result is used in the next
4805                 ifx conditional branch then generate
4806                 code a little differently */
4807                 if (ifx )
4808                         genIfxJump (ifx,"c");
4809                 else
4810                         pic14_outBitC(result);
4811                 /* leave the result in acc */
4812         }
4813         
4814 }
4815 #endif
4816
4817 /*-----------------------------------------------------------------*/
4818 /* genCmpGt :- greater than comparison                             */
4819 /*-----------------------------------------------------------------*/
4820 static void genCmpGt (iCode *ic, iCode *ifx)
4821 {
4822         operand *left, *right, *result;
4823         sym_link *letype , *retype;
4824         int sign ;
4825         
4826         FENTRY;
4827         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4828         left = IC_LEFT(ic);
4829         right= IC_RIGHT(ic);
4830         result = IC_RESULT(ic);
4831         
4832         letype = getSpec(operandType(left));
4833         retype =getSpec(operandType(right));
4834         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4835         /* assign the amsops */
4836         aopOp (left,ic,FALSE);
4837         aopOp (right,ic,FALSE);
4838         aopOp (result,ic,TRUE);
4839         
4840         genCmp(right, left, result, ifx, sign);
4841         
4842         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4843         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4844         freeAsmop(result,NULL,ic,TRUE); 
4845 }
4846
4847 /*-----------------------------------------------------------------*/
4848 /* genCmpLt - less than comparisons                                */
4849 /*-----------------------------------------------------------------*/
4850 static void genCmpLt (iCode *ic, iCode *ifx)
4851 {
4852         operand *left, *right, *result;
4853         sym_link *letype , *retype;
4854         int sign ;
4855         
4856         FENTRY;
4857         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4858         left = IC_LEFT(ic);
4859         right= IC_RIGHT(ic);
4860         result = IC_RESULT(ic);
4861         
4862         letype = getSpec(operandType(left));
4863         retype =getSpec(operandType(right));
4864         sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4865         
4866         /* assign the amsops */
4867         aopOp (left,ic,FALSE);
4868         aopOp (right,ic,FALSE);
4869         aopOp (result,ic,TRUE);
4870         
4871         genCmp(left, right, result, ifx, sign);
4872         
4873         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4874         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4875         freeAsmop(result,NULL,ic,TRUE); 
4876 }
4877
4878 #if 0
4879 /*-----------------------------------------------------------------*/
4880 /* genc16bit2lit - compare a 16 bit value to a literal             */
4881 /*-----------------------------------------------------------------*/
4882 static void genc16bit2lit(operand *op, int lit, int offset)
4883 {
4884         int i;
4885         
4886         FENTRY;
4887         DEBUGpic14_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4888         if( (lit&0xff) == 0) 
4889                 i=1;
4890         else
4891                 i=0;
4892         
4893         switch( BYTEofLONG(lit,i)) { 
4894         case 0:
4895                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4896                 break;
4897         case 1:
4898                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4899                 break;
4900         case 0xff:
4901                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4902                 break;
4903         default:
4904                 emitpcode(POC_MOVFW,popGet(AOP(op),offset+i));
4905                 emitpcode(POC_XORLW,popGetLit(BYTEofLONG(lit,i)));
4906         }
4907         
4908         i ^= 1;
4909         
4910         switch( BYTEofLONG(lit,i)) { 
4911         case 0:
4912                 emitpcode(POC_IORFW,popGet(AOP(op),offset+i));
4913                 break;
4914         case 1:
4915                 emitSKPNZ;
4916                 emitpcode(POC_DECFW,popGet(AOP(op),offset+i));
4917                 break;
4918         case 0xff:
4919                 emitSKPNZ;
4920                 emitpcode(POC_INCFW,popGet(AOP(op),offset+i));
4921                 break;
4922         default:
4923                 emitpcode(POC_MOVLW,popGetLit(BYTEofLONG(lit,i)));
4924                 emitSKPNZ;
4925                 emitpcode(POC_XORFW,popGet(AOP(op),offset+i));
4926                 
4927         }
4928         
4929 }
4930 #endif
4931
4932 #if 0
4933 /*-----------------------------------------------------------------*/
4934 /* gencjneshort - compare and jump if not equal                    */
4935 /*-----------------------------------------------------------------*/
4936 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4937 {
4938         int size = min(AOP_SIZE(left),AOP_SIZE(right));
4939         int offset = 0;
4940         //resolvedIfx rIfx;
4941         symbol *lbl;
4942         
4943         //unsigned long lit = 0L;
4944         FENTRY;
4945         if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
4946           emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
4947           return;
4948         }
4949         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4950         DEBUGpic14_AopType(__LINE__,left,right,result);
4951         
4952         assert (!pic14_sameRegs (AOP(left), AOP(result)));
4953         assert (!pic14_sameRegs (AOP(right), AOP(result)));
4954         if (AOP_SIZE(result)) {
4955           for (offset = 0; offset < AOP_SIZE(result); offset++)
4956             emitpcode (POC_CLRF, popGet (AOP(result), offset));
4957         }
4958         
4959         assert (AOP_SIZE(left) == AOP_SIZE(right));
4960         //resolveIfx(&rIfx,ifx);
4961         lbl = newiTempLabel (NULL);
4962         while (size--)
4963         {
4964           mov2w (AOP(right),size);
4965           emitpcode (POC_XORFW, popGet (AOP(left), size));
4966           if (size)
4967           {
4968             emitSKPZ;
4969             emitpcode (POC_GOTO, popGetLabel (lbl->key));
4970           }
4971         } // while
4972         emitpLabel (lbl->key);
4973         if (AOP_SIZE(result)) {
4974           emitSKPNZ;
4975           emitpcode (POC_INCF, popGet (AOP(result), 0));
4976         } else {
4977           assert (ifx);
4978           genSkipz (ifx, NULL != IC_TRUE(ifx));
4979           ifx->generated = 1;
4980         }
4981         return;
4982 #if 0   
4983         if(result)
4984         {
4985                 DEBUGpic14_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4986                 assert (!pic14_sameRegs (AOP(result), AOP(left)));
4987                 assert (!pic14_sameRegs (AOP(result), AOP(right)));
4988                 for (offset=0; offset < AOP_SIZE(result); offset++)
4989                 {
4990                         emitpcode (POC_CLRF, popGet (AOP(result), offset));
4991                 } // for offset
4992         }
4993         
4994         
4995         /* if the left side is a literal or 
4996         if the right is in a pointer register and left 
4997         is not */
4998         if ((AOP_TYPE(left) == AOP_LIT) || 
4999                 (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5000                 operand *t = right;
5001                 right = left;
5002                 left = t;
5003         }
5004         if(AOP_TYPE(right) == AOP_LIT)
5005                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5006         
5007         /* if the right side is a literal then anything goes */
5008         if (AOP_TYPE(right) == AOP_LIT &&
5009                 AOP_TYPE(left) != AOP_DIR ) {
5010                 switch(size) {
5011                 case 2:
5012                         genc16bit2lit(left, lit, 0);
5013                         emitSKPNZ;
5014                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5015                         break;
5016                 default:
5017                         offset = 0;
5018                         while (size--) {
5019                                 if(lit & 0xff) {
5020                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5021                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5022                                 } else {
5023                                         emitpcode(POC_MOVF,popGet(AOP(left),offset));
5024                                 }
5025                                 
5026                                 emitSKPNZ;
5027                                 emitpcode(POC_GOTO,popGetLabel(lbl->key));
5028                                 offset++;
5029                                 lit >>= 8;
5030                         }
5031                         break;
5032                 }
5033         }
5034         
5035         /* if the right side is in a register or in direct space or
5036         if the left is a pointer register & right is not */    
5037         else if (AOP_TYPE(right) == AOP_REG ||
5038                 AOP_TYPE(right) == AOP_DIR || 
5039                 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5040                 (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5041                 //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5042                 int lbl_key = lbl->key;
5043                 
5044                 if(!result) {
5045                         DEBUGpic14_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5046                         fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5047                                 __FUNCTION__,__LINE__);
5048                         return;
5049                 }
5050                 
5051                 /*     switch(size) { */
5052                 /*     case 2: */
5053                 /*       genc16bit2lit(left, lit, 0); */
5054                 /*       emitSKPNZ; */
5055                 /*       emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
5056                 /*       break; */
5057                 /*     default: */
5058                 offset = 0;
5059                 while (size--) {
5060                         int emit_skip=1;
5061                         if((AOP_TYPE(left) == AOP_DIR) && 
5062                                 ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5063                                 
5064                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5065                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
5066                                 
5067                         } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5068                                 
5069                                 switch (lit & 0xff) {
5070                                 case 0:
5071                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5072                                         break;
5073                                 case 1:
5074                                         emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
5075                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5076                                         emitpcode(POC_GOTO,popGetLabel(lbl->key));
5077                                         emit_skip=0;
5078                                         break;
5079                                 case 0xff:
5080                                         emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5081                                         //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
5082                                         //emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
5083                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5084                                         emit_skip=0;
5085                                         break;
5086                                 default:
5087                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5088                                         emitpcode(POC_XORLW,popGetLit(lit & 0xff));
5089                                 }
5090                                 lit >>= 8;
5091                                 
5092                         } else {
5093                                 emitpcode(POC_MOVF,popGet(AOP(left),offset));
5094                         }
5095                         if(emit_skip) {
5096                                 if(AOP_TYPE(result) == AOP_CRY) {
5097                                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5098                                         if(rIfx.condition)
5099                                                 emitSKPNZ;
5100                                         else
5101                                                 emitSKPZ;
5102                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5103                                 } else {
5104                                         /* fix me. probably need to check result size too */
5105                                         //emitpcode(POC_CLRF,popGet(AOP(result),0));
5106                                         if(rIfx.condition)
5107                                                 emitSKPZ;
5108                                         else
5109                                                 emitSKPNZ;
5110                                         emitpcode(POC_GOTO,popGetLabel(lbl_key));
5111                                 }
5112                                 if(ifx)
5113                                         ifx->generated=1;
5114                         }
5115                         emit_skip++;
5116                         offset++;
5117                 }
5118                 /*       break; */
5119                 /*     } */
5120         } else if(AOP_TYPE(right) == AOP_REG &&
5121                 AOP_TYPE(left) != AOP_DIR){
5122
5123                 offset = 0;
5124                 while(size--) {
5125                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5126                         emitpcode(POC_XORFW,popGet(AOP(right),offset));
5127                         pic14_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5128                         if(rIfx.condition)
5129                                 emitSKPNZ;
5130                         else
5131                                 emitSKPZ;
5132                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5133                         offset++;
5134                 }
5135                 
5136         }else{
5137                 /* right is a pointer reg need both a & b */
5138                 offset = 0;
5139                 while(size--) {
5140                         char *l = aopGet(AOP(left),offset,FALSE,FALSE);
5141                         if(strcmp(l,"b"))
5142                                 pic14_emitcode("mov","b,%s",l);
5143                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5144                         pic14_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5145                         offset++;
5146                 }
5147         }
5148         
5149         emitpcode(POC_INCF,popGet(AOP(result),0));
5150         if(!rIfx.condition)
5151                 emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5152         
5153         emitpLabel(lbl->key);
5154         
5155         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5156         
5157         if(ifx)
5158                 ifx->generated = 1;
5159 #endif
5160 }
5161 #endif
5162
5163 #if 0
5164 /*-----------------------------------------------------------------*/
5165 /* gencjne - compare and jump if not equal                         */
5166 /*-----------------------------------------------------------------*/
5167 static void gencjne(operand *left, operand *right, iCode *ifx)
5168 {
5169         symbol *tlbl  = newiTempLabel(NULL);
5170         
5171         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5172         gencjneshort(left, right, lbl);
5173         
5174         pic14_emitcode("mov","a,%s",one);
5175         pic14_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5176         pic14_emitcode("","%05d_DS_:",lbl->key+100);
5177         pic14_emitcode("clr","a");
5178         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5179         
5180         emitpLabel(lbl->key);
5181         emitpLabel(tlbl->key);
5182         
5183 }
5184 #endif
5185
5186 /*-----------------------------------------------------------------*/
5187 /* genCmpEq - generates code for equal to                          */
5188 /*-----------------------------------------------------------------*/
5189 static void genCmpEq (iCode *ic, iCode *ifx)
5190 {
5191   operand *left, *right, *result;
5192   int size;
5193   symbol *false_label;
5194
5195   FENTRY;
5196   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5197
5198   if(ifx)
5199     DEBUGpic14_emitcode ("; ifx is non-null","");
5200   else
5201     DEBUGpic14_emitcode ("; ifx is null","");
5202
5203   aopOp((left=IC_LEFT(ic)),ic,FALSE);
5204   aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5205   aopOp((result=IC_RESULT(ic)),ic,TRUE);
5206
5207   DEBUGpic14_AopType(__LINE__,left,right,result);
5208
5209   /* if literal, move literal to right */ 
5210   if (op_isLitLike (IC_LEFT(ic))) {
5211     operand *tmp = right ;
5212     right = left;
5213     left = tmp;
5214   }
5215
5216   false_label = NULL;
5217   if (ifx && !IC_TRUE(ifx))
5218   {
5219     assert (IC_FALSE(ifx));
5220     false_label = IC_FALSE(ifx);
5221   }
5222
5223   size = min(AOP_SIZE(left),AOP_SIZE(right));
5224   assert(!pic14_sameRegs(AOP(result),AOP(left)));
5225   assert(!pic14_sameRegs(AOP(result),AOP(right)));
5226
5227   /* assume left != right */
5228   {
5229     int i;
5230     for (i=0; i < AOP_SIZE(result); i++)
5231     {
5232       emitpcode(POC_CLRF, popGet(AOP(result),i));
5233     }
5234   }
5235
5236   if (AOP_TYPE(right) == AOP_LIT)
5237   {
5238     unsigned long lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
5239     int i;
5240     size = AOP_SIZE(left);
5241     assert(!op_isLitLike(left));
5242
5243     switch (lit)
5244     {
5245       case 0:
5246         mov2w(AOP(left), 0);
5247         for (i=1; i < size; i++)
5248           emitpcode(POC_IORFW,popGet(AOP(left),i));
5249         /* now Z is set iff `left == right' */
5250         emitSKPZ;
5251         if (!false_label) false_label = newiTempLabel(NULL);
5252         emitpcode(POC_GOTO, popGetLabel(false_label->key));
5253         break;
5254
5255       default:
5256         for (i=0; i < size; i++)
5257         {
5258           mov2w(AOP(left),i);
5259           emitpcode(POC_XORLW, popGetLit(lit >> (8*i)));
5260           /* now Z is cleared if `left != right' */
5261           emitSKPZ;
5262           if (!false_label) false_label = newiTempLabel(NULL);
5263           emitpcode(POC_GOTO, popGetLabel(false_label->key));
5264         } // for i
5265         break;
5266     } // switch (lit)
5267   }
5268   else
5269   {
5270     /* right is no literal */
5271     int i;
5272
5273     for (i=0; i < size; i++)
5274     {
5275       mov2w(AOP(right),i);
5276       emitpcode(POC_XORFW,popGet(AOP(left),i));
5277       /* now Z is cleared if `left != right' */
5278       emitSKPZ;
5279       if (!false_label) false_label = newiTempLabel(NULL);
5280       emitpcode(POC_GOTO, popGetLabel(false_label->key));
5281     } // for i
5282   }
5283
5284   /* if we reach here, left == right */
5285
5286   if (AOP_SIZE(result) > 0)
5287   {
5288     emitpcode(POC_INCF, popGet(AOP(result),0));
5289   }
5290
5291   if (ifx && IC_TRUE(ifx))
5292   {
5293     emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
5294   }
5295
5296   if (false_label && (!ifx || IC_TRUE(ifx)))
5297     emitpLabel(false_label->key);
5298
5299   if (ifx) ifx->generated = 1;
5300
5301   freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5302   freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5303   freeAsmop(result,NULL,ic,TRUE);
5304 }
5305
5306 /*-----------------------------------------------------------------*/
5307 /* ifxForOp - returns the icode containing the ifx for operand     */
5308 /*-----------------------------------------------------------------*/
5309 static iCode *ifxForOp ( operand *op, iCode *ic )
5310 {
5311         FENTRY;
5312         /* if true symbol then needs to be assigned */
5313         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5314         if (IS_TRUE_SYMOP(op))
5315                 return NULL ;
5316         
5317         /* if this has register type condition and
5318         the next instruction is ifx with the same operand
5319         and live to of the operand is upto the ifx only then */
5320         if (ic->next &&
5321                 ic->next->op == IFX &&
5322                 IC_COND(ic->next)->key == op->key &&
5323                 OP_SYMBOL(op)->liveTo <= ic->next->seq )
5324                 return ic->next;
5325         
5326         if (ic->next &&
5327                 ic->next->op == IFX &&
5328                 IC_COND(ic->next)->key == op->key) {
5329                 DEBUGpic14_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5330                 return ic->next;
5331         }
5332         
5333         DEBUGpic14_emitcode ("; NULL :(","%d",__LINE__);
5334         if (ic->next &&
5335                 ic->next->op == IFX)
5336                 DEBUGpic14_emitcode ("; ic-next"," is an IFX");
5337         
5338         if (ic->next &&
5339                 ic->next->op == IFX &&
5340                 IC_COND(ic->next)->key == op->key) {
5341                 DEBUGpic14_emitcode ("; "," key is okay");
5342                 DEBUGpic14_emitcode ("; "," key liveTo %d, next->seq = %d",
5343                         OP_SYMBOL(op)->liveTo,
5344                         ic->next->seq);
5345         }
5346         
5347         
5348         return NULL;
5349 }
5350 /*-----------------------------------------------------------------*/
5351 /* genAndOp - for && operation                                     */
5352 /*-----------------------------------------------------------------*/
5353 static void genAndOp (iCode *ic)
5354 {
5355         operand *left,*right, *result;
5356         /*     symbol *tlbl; */
5357         
5358         FENTRY;
5359         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5360         /* note here that && operations that are in an
5361         if statement are taken away by backPatchLabels
5362         only those used in arthmetic operations remain */
5363         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5364         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5365         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5366         
5367         DEBUGpic14_AopType(__LINE__,left,right,result);
5368         
5369         emitpcode(POC_MOVFW,popGet(AOP(left),0));
5370         emitpcode(POC_ANDFW,popGet(AOP(right),0));
5371         emitpcode(POC_MOVWF,popGet(AOP(result),0));
5372         
5373         /* if both are bit variables */
5374         /*     if (AOP_TYPE(left) == AOP_CRY && */
5375         /*         AOP_TYPE(right) == AOP_CRY ) { */
5376         /*         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5377         /*         pic14_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5378         /*         pic14_outBitC(result); */
5379         /*     } else { */
5380         /*         tlbl = newiTempLabel(NULL); */
5381         /*         pic14_toBoolean(left);     */
5382         /*         pic14_emitcode("jz","%05d_DS_",tlbl->key+100); */
5383         /*         pic14_toBoolean(right); */
5384         /*         pic14_emitcode("","%05d_DS_:",tlbl->key+100); */
5385         /*         pic14_outBitAcc(result); */
5386         /*     } */
5387         
5388         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5389         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5390         freeAsmop(result,NULL,ic,TRUE);
5391 }
5392
5393
5394 /*-----------------------------------------------------------------*/
5395 /* genOrOp - for || operation                                      */
5396 /*-----------------------------------------------------------------*/
5397 /*
5398 tsd pic port -
5399 modified this code, but it doesn't appear to ever get called
5400 */
5401
5402 static void genOrOp (iCode *ic)
5403 {
5404         operand *left,*right, *result;
5405         symbol *tlbl;
5406         int i;
5407         
5408         /* note here that || operations that are in an
5409         if statement are taken away by backPatchLabels
5410         only those used in arthmetic operations remain */
5411         FENTRY;
5412         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5413         aopOp((left=IC_LEFT(ic)),ic,FALSE);
5414         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5415         aopOp((result=IC_RESULT(ic)),ic,FALSE);
5416         
5417         DEBUGpic14_AopType(__LINE__,left,right,result);
5418
5419         for (i=0; i < AOP_SIZE(result); i++)
5420         {
5421                 emitpcode(POC_CLRF, popGet(AOP(result), i));
5422         } // for i
5423
5424         tlbl = newiTempLabel(NULL);
5425         pic14_toBoolean(left);
5426         emitSKPZ;
5427         emitpcode(POC_GOTO, popGetLabel(tlbl->key));
5428         pic14_toBoolean(right);
5429         emitpLabel(tlbl->key);
5430         /* here Z is clear IFF `left || right' */
5431         emitSKPZ;
5432         emitpcode(POC_INCF, popGet(AOP(result), 0));
5433         
5434         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5435         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5436         freeAsmop(result,NULL,ic,TRUE);            
5437 }
5438
5439 /*-----------------------------------------------------------------*/
5440 /* isLiteralBit - test if lit == 2^n                               */
5441 /*-----------------------------------------------------------------*/
5442 static int isLiteralBit(unsigned long lit)
5443 {
5444         unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5445                 0x100L,0x200L,0x400L,0x800L,
5446                 0x1000L,0x2000L,0x4000L,0x8000L,
5447                 0x10000L,0x20000L,0x40000L,0x80000L,
5448                 0x100000L,0x200000L,0x400000L,0x800000L,
5449                 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5450                 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5451         int idx;
5452         
5453         FENTRY;
5454         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5455         for(idx = 0; idx < 32; idx++)
5456                 if(lit == pw[idx])
5457                         return idx+1;
5458                 return 0;
5459 }
5460
5461 /*-----------------------------------------------------------------*/
5462 /* continueIfTrue -                                                */
5463 /*-----------------------------------------------------------------*/
5464 static void continueIfTrue (iCode *ic)
5465 {
5466         FENTRY;
5467         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5468         if(IC_TRUE(ic))
5469                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5470         ic->generated = 1;
5471 }
5472
5473 /*-----------------------------------------------------------------*/
5474 /* jmpIfTrue -                                                     */
5475 /*-----------------------------------------------------------------*/
5476 static void jumpIfTrue (iCode *ic)
5477 {
5478         FENTRY;
5479         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5480         if(!IC_TRUE(ic))
5481                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5482         ic->generated = 1;
5483 }
5484
5485 /*-----------------------------------------------------------------*/
5486 /* jmpTrueOrFalse -                                                */
5487 /*-----------------------------------------------------------------*/
5488 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5489 {
5490         FENTRY;
5491         // ugly but optimized by peephole
5492         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5493         if(IC_TRUE(ic)){
5494                 symbol *nlbl = newiTempLabel(NULL);
5495                 pic14_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5496                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5497                 pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5498                 pic14_emitcode("","%05d_DS_:",nlbl->key+100);
5499         }
5500         else{
5501                 pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5502                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5503         }
5504         ic->generated = 1;
5505 }
5506
5507 /*-----------------------------------------------------------------*/
5508 /* genAnd  - code for and                                          */
5509 /*-----------------------------------------------------------------*/
5510 static void genAnd (iCode *ic, iCode *ifx)
5511 {
5512         operand *left, *right, *result;
5513         int size, offset=0;  
5514         unsigned long lit = 0L;
5515         int bytelit = 0;
5516         resolvedIfx rIfx;
5517         
5518         FENTRY;
5519         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5520         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5521         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5522         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5523         
5524         resolveIfx(&rIfx,ifx);
5525         
5526         /* if left is a literal & right is not then exchange them */
5527         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5528                 AOP_NEEDSACC(left)) {
5529                 operand *tmp = right ;
5530                 right = left;
5531                 left = tmp;
5532         }
5533         
5534         /* if result = right then exchange them */
5535         if(pic14_sameRegs(AOP(result),AOP(right))){
5536                 operand *tmp = right ;
5537                 right = left;
5538                 left = tmp;
5539         }
5540         
5541         /* if right is bit then exchange them */
5542         if (AOP_TYPE(right) == AOP_CRY &&
5543                 AOP_TYPE(left) != AOP_CRY){
5544                 operand *tmp = right ;
5545                 right = left;
5546                 left = tmp;
5547         }
5548         if(AOP_TYPE(right) == AOP_LIT)
5549                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5550         
5551         size = AOP_SIZE(result);
5552         
5553         DEBUGpic14_AopType(__LINE__,left,right,result);
5554         
5555         // if(bit & yy)
5556         // result = bit & yy;
5557         if (AOP_TYPE(left) == AOP_CRY){
5558                 // c = bit & literal;
5559                 if(AOP_TYPE(right) == AOP_LIT){
5560                         if(lit & 1) {
5561                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5562                                         // no change
5563                                         goto release;
5564                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5565                         } else {
5566                                 // bit(result) = 0;
5567                                 if(size && (AOP_TYPE(result) == AOP_CRY)){
5568                                         pic14_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5569                                         goto release;
5570                                 }
5571                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5572                                         jumpIfTrue(ifx);
5573                                         goto release;
5574                                 }
5575                                 pic14_emitcode("clr","c");
5576                         }
5577                 } else {
5578                         if (AOP_TYPE(right) == AOP_CRY){
5579                                 // c = bit & bit;
5580                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5581                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5582                         } else {
5583                                 // c = bit & val;
5584                                 MOVA(aopGet(AOP(right),0,FALSE,FALSE));
5585                                 // c = lsb
5586                                 pic14_emitcode("rrc","a");
5587                                 pic14_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5588                         }
5589                 }
5590                 // bit = c
5591                 // val = c
5592                 if(size)
5593                         pic14_outBitC(result);
5594                 // if(bit & ...)
5595                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5596                         genIfxJump(ifx, "c");           
5597                 goto release ;
5598         }
5599         
5600         // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5601         // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5602         if((AOP_TYPE(right) == AOP_LIT) &&
5603                 (AOP_TYPE(result) == AOP_CRY) &&
5604                 (AOP_TYPE(left) != AOP_CRY)){
5605                 int posbit = isLiteralBit(lit);
5606                 /* left &  2^n */
5607                 if(posbit){
5608                         posbit--;
5609                         //MOVA(aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5610                         // bit = left & 2^n
5611                         if(size)
5612                                 pic14_emitcode("mov","c,acc.%d",posbit&0x07);
5613                         // if(left &  2^n)
5614                         else{
5615                                 if(ifx){
5616                                         int offset = 0;
5617                                         while (posbit > 7) {
5618                                                 posbit -= 8;
5619                                                 offset++;
5620                                         }
5621                                         emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5622                                                 newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit,0));
5623                                         emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
5624                                         
5625                                         ifx->generated = 1;
5626                                 }
5627                                 goto release;
5628                         }
5629                 } else {
5630                         symbol *tlbl = newiTempLabel(NULL);
5631                         int sizel = AOP_SIZE(left);
5632                         if(size)
5633                                 pic14_emitcode("setb","c");
5634                         while(sizel--){
5635                                 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5636                                         MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
5637                                         // byte ==  2^n ?
5638                                         if((posbit = isLiteralBit(bytelit)) != 0)
5639                                                 pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5640                                         else{
5641                                                 if(bytelit != 0x0FFL)
5642                                                         pic14_emitcode("anl","a,%s",
5643                                                         aopGet(AOP(right),offset,FALSE,TRUE));
5644                                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5645                                         }
5646                                 }
5647                                 offset++;
5648                         }
5649                         // bit = left & literal
5650                         if(size){
5651                                 pic14_emitcode("clr","c");
5652                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5653                         }
5654                         // if(left & literal)
5655                         else{
5656                                 if(ifx)
5657                                         jmpTrueOrFalse(ifx, tlbl);
5658                                 goto release ;
5659                         }
5660                 }
5661                 pic14_outBitC(result);
5662                 goto release ;
5663         }
5664         
5665         /* if left is same as result */
5666         if(pic14_sameRegs(AOP(result),AOP(left))){
5667                 int know_W = -1;
5668                 for(;size--; offset++,lit>>=8) {
5669                         if(AOP_TYPE(right) == AOP_LIT){
5670                                 switch(lit & 0xff) {
5671                                 case 0x00:
5672                                         /*  and'ing with 0 has clears the result */
5673                                         emitpcode(POC_CLRF,popGet(AOP(result),offset));
5674                                         break;
5675                                 case 0xff:
5676                                         /* and'ing with 0xff is a nop when the result and left are the same */
5677                                         break;
5678                                         
5679                                 default:
5680                                         {
5681                                                 int p = my_powof2( (~lit) & 0xff );
5682                                                 if(p>=0) {
5683                                                         /* only one bit is set in the literal, so use a bcf instruction */
5684                                                         emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5685                                                         
5686                                                 } else {
5687                                                         if(know_W != (int)(lit&0xff))
5688                                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5689                                                         know_W = lit &0xff;
5690                                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5691                                                 }
5692                                         }    
5693                                 }
5694                         } else {
5695                                 if (AOP_TYPE(left) == AOP_ACC) {
5696                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5697                                 } else {        
5698                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5699                                         emitpcode(POC_ANDWF,popGet(AOP(left),offset));
5700                                         
5701                                 }
5702                         }
5703                 }
5704                 
5705         } else {
5706                 // left & result in different registers
5707                 if(AOP_TYPE(result) == AOP_CRY){
5708                         // result = bit
5709                         // if(size), result in bit
5710                         // if(!size && ifx), conditional oper: if(left & right)
5711                         symbol *tlbl = newiTempLabel(NULL);
5712                         int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5713                         if(size)
5714                                 pic14_emitcode("setb","c");
5715                         while(sizer--){
5716                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
5717                                 pic14_emitcode("anl","a,%s",
5718                                         aopGet(AOP(left),offset,FALSE,FALSE));
5719                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
5720                                 offset++;
5721                         }
5722                         if(size){
5723                                 CLRC;
5724                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5725                                 pic14_outBitC(result);
5726                         } else if(ifx)
5727                                 jmpTrueOrFalse(ifx, tlbl);
5728                 } else {
5729                         for(;(size--);offset++) {
5730                                 // normal case
5731                                 // result = left & right
5732                                 if(AOP_TYPE(right) == AOP_LIT){
5733                                         int t = (lit >> (offset*8)) & 0x0FFL;
5734                                         switch(t) { 
5735                                         case 0x00:
5736                                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
5737                                                 break;
5738                                         case 0xff:
5739                                                 if(AOP_TYPE(left) != AOP_ACC) {
5740                                                         emitpcode(POC_MOVFW,popGet(AOP(left),offset));
5741                                                 }
5742                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5743                                                 break;
5744                                         default:
5745                                                 if(AOP_TYPE(left) == AOP_ACC) {
5746                                                         emitpcode(POC_ANDLW, popGetLit(t));
5747                                                 } else {
5748                                                         emitpcode(POC_MOVLW, popGetLit(t));
5749                                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5750                                                 }
5751                                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5752                                         }
5753                                         continue;
5754                                 }
5755                                 
5756                                 if (AOP_TYPE(left) == AOP_ACC) {
5757                                         emitpcode(POC_ANDFW,popGet(AOP(right),offset));
5758                                 } else {
5759                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
5760                                         emitpcode(POC_ANDFW,popGet(AOP(left),offset));
5761                                 }
5762                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
5763                         }
5764                 }
5765         }
5766         
5767 release :
5768         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5769         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5770         freeAsmop(result,NULL,ic,TRUE);     
5771 }
5772
5773 /*-----------------------------------------------------------------*/
5774 /* genOr  - code for or                                            */
5775 /*-----------------------------------------------------------------*/
5776 static void genOr (iCode *ic, iCode *ifx)
5777 {
5778         operand *left, *right, *result;
5779         int size, offset=0;
5780         unsigned long lit = 0L;
5781         
5782         FENTRY;
5783         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5784         
5785         aopOp((left = IC_LEFT(ic)),ic,FALSE);
5786         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5787         aopOp((result=IC_RESULT(ic)),ic,TRUE);
5788         
5789         DEBUGpic14_AopType(__LINE__,left,right,result);
5790         
5791         /* if left is a literal & right is not then exchange them */
5792         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5793                 AOP_NEEDSACC(left)) {
5794                 operand *tmp = right ;
5795                 right = left;
5796                 left = tmp;
5797         }
5798         
5799         /* if result = right then exchange them */
5800         if(pic14_sameRegs(AOP(result),AOP(right))){
5801                 operand *tmp = right ;
5802                 right = left;
5803                 left = tmp;
5804         }
5805         
5806         /* if right is bit then exchange them */
5807         if (AOP_TYPE(right) == AOP_CRY &&
5808                 AOP_TYPE(left) != AOP_CRY){
5809                 operand *tmp = right ;
5810                 right = left;
5811                 left = tmp;
5812         }
5813         
5814         DEBUGpic14_AopType(__LINE__,left,right,result);
5815         
5816         if(AOP_TYPE(right) == AOP_LIT)
5817                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5818         
5819         size = AOP_SIZE(result);
5820         
5821         // if(bit | yy)
5822         // xx = bit | yy;
5823         if (AOP_TYPE(left) == AOP_CRY){
5824                 if(AOP_TYPE(right) == AOP_LIT){
5825                         // c = bit & literal;
5826                         if(lit){
5827                                 // lit != 0 => result = 1
5828                                 if(AOP_TYPE(result) == AOP_CRY){
5829                                         if(size)
5830                                                 emitpcode(POC_BSF, popGet(AOP(result),0));
5831                                         //pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5832                                         //   AOP(result)->aopu.aop_dir,
5833                                         //   AOP(result)->aopu.aop_dir);
5834                                         else if(ifx)
5835                                                 continueIfTrue(ifx);
5836                                         goto release;
5837                                 }
5838                         } else {
5839                                 // lit == 0 => result = left
5840                                 if(size && pic14_sameRegs(AOP(result),AOP(left)))
5841                                         goto release;
5842                                 pic14_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5843                         }
5844                 } else {
5845                         if (AOP_TYPE(right) == AOP_CRY){
5846                                 if(pic14_sameRegs(AOP(result),AOP(left))){
5847                                         // c = bit | bit;
5848                                         emitpcode(POC_BCF,   popGet(AOP(result),0));
5849                                         emitpcode(POC_BTFSC, popGet(AOP(right),0));
5850                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5851                                         
5852                                         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5853                                                 AOP(result)->aopu.aop_dir,
5854                                                 AOP(result)->aopu.aop_dir);
5855                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5856                                                 AOP(right)->aopu.aop_dir,
5857                                                 AOP(right)->aopu.aop_dir);
5858                                         pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5859                                                 AOP(result)->aopu.aop_dir,
5860                                                 AOP(result)->aopu.aop_dir);
5861                                 } else {
5862                                         if( AOP_TYPE(result) == AOP_ACC) {
5863                                                 emitpcode(POC_MOVLW, popGetLit(0));
5864                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5865                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5866                                                 emitpcode(POC_MOVLW, popGetLit(1));
5867                                                 
5868                                         } else {
5869                                                 
5870                                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5871                                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
5872                                                 emitpcode(POC_BTFSC, popGet(AOP(left),0));
5873                                                 emitpcode(POC_BSF,   popGet(AOP(result),0));
5874                                                 
5875                                                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
5876                                                         AOP(result)->aopu.aop_dir,
5877                                                         AOP(result)->aopu.aop_dir);
5878                                                 pic14_emitcode("btfss","(%s >> 3), (%s & 7)",
5879                                                         AOP(right)->aopu.aop_dir,
5880                                                         AOP(right)->aopu.aop_dir);
5881                                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
5882                                                         AOP(left)->aopu.aop_dir,
5883                                                         AOP(left)->aopu.aop_dir);
5884                                                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
5885                                                         AOP(result)->aopu.aop_dir,
5886                                                         AOP(result)->aopu.aop_dir);
5887                                         }
5888                                 }
5889                         } else {
5890                                 // c = bit | val;
5891                                 symbol *tlbl = newiTempLabel(NULL);
5892                                 pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5893                                 
5894                                 
5895                                 emitpcode(POC_BCF,   popGet(AOP(result),0));
5896                                 if( AOP_TYPE(right) == AOP_ACC) {
5897                                         emitpcode(POC_IORLW, popGetLit(0));
5898                                         emitSKPNZ;
5899                                         emitpcode(POC_BTFSC, popGet(AOP(left),0));
5900                                         emitpcode(POC_BSF,   popGet(AOP(result),0));
5901                                 }
5902                                 
5903                                 
5904                                 
5905                                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5906                                         pic14_emitcode(";XXX setb","c");
5907                                 pic14_emitcode(";XXX jb","%s,%05d_DS_",
5908                                         AOP(left)->aopu.aop_dir,tlbl->key+100);
5909                                 pic14_toBoolean(right);
5910                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5911                                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5912                                         jmpTrueOrFalse(ifx, tlbl);
5913                                         goto release;
5914                                 } else {
5915                                         CLRC;
5916                                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5917                                 }
5918                         }
5919                 }
5920                 // bit = c
5921                 // val = c
5922                 if(size)
5923                         pic14_outBitC(result);
5924                 // if(bit | ...)
5925                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5926                         genIfxJump(ifx, "c");           
5927                 goto release ;
5928         }
5929
5930         // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5931         // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5932         if((AOP_TYPE(right) == AOP_LIT) &&
5933           (AOP_TYPE(result) == AOP_CRY) &&
5934           (AOP_TYPE(left) != AOP_CRY)){
5935                 if(lit){
5936                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5937                         // result = 1
5938                         if(size)
5939                                 pic14_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5940                         else 
5941                                 continueIfTrue(ifx);
5942                         goto release;
5943                 } else {
5944                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5945                         // lit = 0, result = boolean(left)
5946                         if(size)
5947                                 pic14_emitcode(";XXX setb","c");
5948                         pic14_toBoolean(right);
5949                         if(size){
5950                                 symbol *tlbl = newiTempLabel(NULL);
5951                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5952                                 CLRC;
5953                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
5954                         } else {
5955                                 genIfxJump (ifx,"a");
5956                                 goto release;
5957                         }
5958                 }
5959                 pic14_outBitC(result);
5960                 goto release ;
5961         }
5962
5963         /* if left is same as result */
5964         if(pic14_sameRegs(AOP(result),AOP(left))){
5965                 int know_W = -1;
5966                 for(;size--; offset++,lit>>=8) {
5967                         if(AOP_TYPE(right) == AOP_LIT){
5968                                 if((lit & 0xff) == 0)
5969                                         /*  or'ing with 0 has no effect */
5970                                         continue;
5971                                 else {
5972                                         int p = my_powof2(lit & 0xff);
5973                                         if(p>=0) {
5974                                                 /* only one bit is set in the literal, so use a bsf instruction */
5975                                                 emitpcode(POC_BSF,
5976                                                         newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5977                                         } else {
5978                                                 if(know_W != (int)(lit & 0xff))
5979                                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
5980                                                 know_W = lit & 0xff;
5981                                                 emitpcode(POC_IORWF, popGet(AOP(left),offset));
5982                                         }
5983                                         
5984                                 }
5985                         } else {
5986                                 if (AOP_TYPE(left) == AOP_ACC) {
5987                                         emitpcode(POC_IORFW,  popGet(AOP(right),offset));
5988                                         pic14_emitcode("iorwf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5989                                 } else {        
5990                                         emitpcode(POC_MOVFW,  popGet(AOP(right),offset));
5991                                         emitpcode(POC_IORWF,  popGet(AOP(left),offset));
5992                                         
5993                                         pic14_emitcode("movf","%s,w",aopGet(AOP(right),offset,FALSE,FALSE));
5994                                         pic14_emitcode("iorwf","%s,f",aopGet(AOP(left),offset,FALSE,FALSE));
5995                                         
5996                                 }
5997                         }
5998                 }
5999         } else {
6000                 // left & result in different registers
6001                 if(AOP_TYPE(result) == AOP_CRY){
6002                         // result = bit
6003                         // if(size), result in bit
6004                         // if(!size && ifx), conditional oper: if(left | right)
6005                         symbol *tlbl = newiTempLabel(NULL);
6006                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6007                         pic14_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6008                         
6009                         
6010                         if(size)
6011                                 pic14_emitcode(";XXX setb","c");
6012                         while(sizer--){
6013                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6014                                 pic14_emitcode(";XXX orl","a,%s",
6015                                         aopGet(AOP(left),offset,FALSE,FALSE));
6016                                 pic14_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6017                                 offset++;
6018                         }
6019                         if(size){
6020                                 CLRC;
6021                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6022                                 pic14_outBitC(result);
6023                         } else if(ifx)
6024                                 jmpTrueOrFalse(ifx, tlbl);
6025                 } else for(;(size--);offset++){
6026                         // normal case
6027                         // result = left | right
6028                         if(AOP_TYPE(right) == AOP_LIT){
6029                                 int t = (lit >> (offset*8)) & 0x0FFL;
6030                                 switch(t) { 
6031                                 case 0x00:
6032                                         if (AOP_TYPE(left) != AOP_ACC) {
6033                                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
6034                                         }
6035                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6036                                         
6037                                         break;
6038                                 default:
6039                                         if (AOP_TYPE(left) == AOP_ACC) {
6040                                                 emitpcode(POC_IORLW,  popGetLit(t));
6041                                         } else {
6042                                                 emitpcode(POC_MOVLW,  popGetLit(t));
6043                                                 emitpcode(POC_IORFW,  popGet(AOP(left),offset));
6044                                         }
6045                                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));        
6046                                 }
6047                                 continue;
6048                         }
6049                         
6050                         // faster than result <- left, anl result,right
6051                         // and better if result is SFR
6052                         if (AOP_TYPE(left) == AOP_ACC) {
6053                                 emitpcode(POC_IORFW,popGet(AOP(right),offset));
6054                         } else {
6055                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6056                                 emitpcode(POC_IORFW,popGet(AOP(left),offset));
6057                         }
6058                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
6059                 }
6060         }
6061
6062 release :
6063         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6064         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6065         freeAsmop(result,NULL,ic,TRUE);     
6066 }
6067
6068 /*-----------------------------------------------------------------*/
6069 /* genXor - code for xclusive or                                   */
6070 /*-----------------------------------------------------------------*/
6071 static void genXor (iCode *ic, iCode *ifx)
6072 {
6073         operand *left, *right, *result;
6074         int size, offset=0;
6075         unsigned long lit = 0L;
6076         
6077         FENTRY;
6078         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6079         
6080         aopOp((left = IC_LEFT(ic)),ic,FALSE);
6081         aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6082         aopOp((result=IC_RESULT(ic)),ic,TRUE);
6083         
6084         /* if left is a literal & right is not ||
6085         if left needs acc & right does not */
6086         if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6087                 (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6088                 operand *tmp = right ;
6089                 right = left;
6090                 left = tmp;
6091         }
6092         
6093         /* if result = right then exchange them */
6094         if(pic14_sameRegs(AOP(result),AOP(right))){
6095                 operand *tmp = right ;
6096                 right = left;
6097                 left = tmp;
6098         }
6099         
6100         /* if right is bit then exchange them */
6101         if (AOP_TYPE(right) == AOP_CRY &&
6102                 AOP_TYPE(left) != AOP_CRY){
6103                 operand *tmp = right ;
6104                 right = left;
6105                 left = tmp;
6106         }
6107         if(AOP_TYPE(right) == AOP_LIT)
6108                 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6109         
6110         size = AOP_SIZE(result);
6111         
6112         // if(bit ^ yy)
6113         // xx = bit ^ yy;
6114         if (AOP_TYPE(left) == AOP_CRY){
6115                 if(AOP_TYPE(right) == AOP_LIT){
6116                         // c = bit & literal;
6117                         if(lit>>1){
6118                                 // lit>>1  != 0 => result = 1
6119                                 if(AOP_TYPE(result) == AOP_CRY){
6120                                         if(size)
6121                                         {emitpcode(POC_BSF,  popGet(AOP(result),offset));
6122                                         pic14_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6123                                         else if(ifx)
6124                                                 continueIfTrue(ifx);
6125                                         goto release;
6126                                 }
6127                                 pic14_emitcode("setb","c");
6128                         } else{
6129                                 // lit == (0 or 1)
6130                                 if(lit == 0){
6131                                         // lit == 0, result = left
6132                                         if(size && pic14_sameRegs(AOP(result),AOP(left)))
6133                                                 goto release;
6134                                         pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6135                                 } else{
6136                                         // lit == 1, result = not(left)
6137                                         if(size && pic14_sameRegs(AOP(result),AOP(left))){
6138                                                 emitpcode(POC_MOVLW,  popGet(AOP(result),offset));
6139                                                 emitpcode(POC_XORWF,  popGet(AOP(result),offset));
6140                                                 pic14_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6141                                                 goto release;
6142                                         } else {
6143                                                 assert ( !"incomplete genXor" );
6144                                                 pic14_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6145                                                 pic14_emitcode("cpl","c");
6146                                         }
6147                                 }
6148                         }
6149                         
6150                 } else {
6151                         // right != literal
6152                         symbol *tlbl = newiTempLabel(NULL);
6153                         if (AOP_TYPE(right) == AOP_CRY){
6154                                 // c = bit ^ bit;
6155                                 pic14_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6156                         }
6157                         else{
6158                                 int sizer = AOP_SIZE(right);
6159                                 // c = bit ^ val
6160                                 // if val>>1 != 0, result = 1
6161                                 pic14_emitcode("setb","c");
6162                                 while(sizer){
6163                                         MOVA(aopGet(AOP(right),sizer-1,FALSE,FALSE));
6164                                         if(sizer == 1)
6165                                                 // test the msb of the lsb
6166                                                 pic14_emitcode("anl","a,#0xfe");
6167                                         pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6168                                         sizer--;
6169                                 }
6170                                 // val = (0,1)
6171                                 pic14_emitcode("rrc","a");
6172                         }
6173                         pic14_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6174                         pic14_emitcode("cpl","c");
6175                         pic14_emitcode("","%05d_DS_:",(tlbl->key+100));
6176                 }
6177                 // bit = c
6178                 // val = c
6179                 if(size)
6180                         pic14_outBitC(result);
6181                 // if(bit | ...)
6182                 else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6183                         genIfxJump(ifx, "c");           
6184                 goto release ;
6185         }
6186         
6187         if(pic14_sameRegs(AOP(result),AOP(left))){
6188                 /* if left is same as result */
6189                 for(;size--; offset++) {
6190                         if(AOP_TYPE(right) == AOP_LIT){
6191                                 int t  = (lit >> (offset*8)) & 0x0FFL;
6192                                 if(t == 0x00L)
6193                                         continue;
6194                                 else
6195                                         if (IS_AOP_PREG(left)) {
6196                                                 MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6197                                                 pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6198                                                 aopPut(AOP(result),"a",offset);
6199                                         } else {
6200                                                 emitpcode(POC_MOVLW, popGetLit(t));
6201                                                 emitpcode(POC_XORWF,popGet(AOP(left),offset));
6202                                                 pic14_emitcode("xrl","%s,%s",
6203                                                         aopGet(AOP(left),offset,FALSE,TRUE),
6204                                                         aopGet(AOP(right),offset,FALSE,FALSE));
6205                                         }
6206                         } else {
6207                                 if (AOP_TYPE(left) == AOP_ACC)
6208                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(right),offset,FALSE,FALSE));
6209                                 else {
6210                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6211                                         emitpcode(POC_XORWF,popGet(AOP(left),offset));
6212                                         /*
6213                                         if (IS_AOP_PREG(left)) {
6214                                         pic14_emitcode("xrl","a,%s",aopGet(AOP(left),offset,FALSE,TRUE));
6215                                         aopPut(AOP(result),"a",offset);
6216                                         } else
6217                                         pic14_emitcode("xrl","%s,a",
6218                                         aopGet(AOP(left),offset,FALSE,TRUE));
6219                                         */
6220                                 }
6221                         }
6222                 }
6223         } else {
6224                 // left & result in different registers
6225                 if(AOP_TYPE(result) == AOP_CRY){
6226                         // result = bit
6227                         // if(size), result in bit
6228                         // if(!size && ifx), conditional oper: if(left ^ right)
6229                         symbol *tlbl = newiTempLabel(NULL);
6230                         int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6231                         if(size)
6232                                 pic14_emitcode("setb","c");
6233                         while(sizer--){
6234                                 if((AOP_TYPE(right) == AOP_LIT) &&
6235                                         (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6236                                         MOVA(aopGet(AOP(left),offset,FALSE,FALSE));
6237                                 } else {
6238                                         MOVA(aopGet(AOP(right),offset,FALSE,FALSE));
6239                                         pic14_emitcode("xrl","a,%s",
6240                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6241                                 }
6242                                 pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
6243                                 offset++;
6244                         }
6245                         if(size){
6246                                 CLRC;
6247                                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6248                                 pic14_outBitC(result);
6249                         } else if(ifx)
6250                                 jmpTrueOrFalse(ifx, tlbl);
6251                 } else for(;(size--);offset++){
6252                         // normal case
6253                         // result = left & right
6254                         if(AOP_TYPE(right) == AOP_LIT){
6255                                 int t = (lit >> (offset*8)) & 0x0FFL;
6256                                 switch(t) { 
6257                                 case 0x00:
6258                                         if (AOP_TYPE(left) != AOP_ACC) {
6259                                                 emitpcode(POC_MOVFW,popGet(AOP(left),offset));
6260                                         }
6261                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6262                                         pic14_emitcode("movf","%s,w",
6263                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6264                                         pic14_emitcode("movwf","%s",
6265                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6266                                         break;
6267                                 case 0xff:
6268                                         if (AOP_TYPE(left) == AOP_ACC) {
6269                                                 emitpcode(POC_XORLW, popGetLit(t));
6270                                         } else {
6271                                                 emitpcode(POC_COMFW,popGet(AOP(left),offset));
6272                                         }
6273                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6274                                         break;
6275                                 default:
6276                                         if (AOP_TYPE(left) == AOP_ACC) {
6277                                                 emitpcode(POC_XORLW, popGetLit(t));
6278                                         } else {
6279                                                 emitpcode(POC_MOVLW, popGetLit(t));
6280                                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6281                                         }
6282                                         emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6283                                         pic14_emitcode("movlw","0x%x",t);
6284                                         pic14_emitcode("xorwf","%s,w",
6285                                                 aopGet(AOP(left),offset,FALSE,FALSE));
6286                                         pic14_emitcode("movwf","%s",
6287                                                 aopGet(AOP(result),offset,FALSE,FALSE));
6288                                         
6289                                 }
6290                                 continue;
6291                         }
6292                         
6293                         // faster than result <- left, anl result,right
6294                         // and better if result is SFR
6295                         if (AOP_TYPE(left) == AOP_ACC) {
6296                                 emitpcode(POC_XORFW,popGet(AOP(right),offset));
6297                         } else {
6298                                 emitpcode(POC_MOVFW,popGet(AOP(right),offset));
6299                                 emitpcode(POC_XORFW,popGet(AOP(left),offset));
6300                         }
6301                         if ( AOP_TYPE(result) != AOP_ACC){
6302                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
6303                         }
6304                 }
6305         }
6306         
6307 release :
6308         freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6309         freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6310         freeAsmop(result,NULL,ic,TRUE);     
6311 }
6312
6313 /*-----------------------------------------------------------------*/
6314 /* genInline - write the inline code out                           */
6315 /*-----------------------------------------------------------------*/
6316 static void genInline (iCode *ic)
6317 {
6318   char *buffer, *bp, *bp1;
6319
6320   FENTRY;
6321   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6322
6323   _G.inLine += (!options.asmpeep);
6324
6325   buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6326   strcpy(buffer,IC_INLINE(ic));
6327
6328   /* emit each line as a code */
6329   while (*bp) {
6330     if (*bp == '\n') {
6331       *bp++ = '\0';
6332       
6333       if(*bp1)
6334         addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6335       bp1 = bp;
6336     } else {
6337       if (*bp == ':') {
6338         bp++;
6339         *bp = '\0';
6340         bp++;
6341
6342         /* print label, use this special format with NULL directive
6343          * to denote that the argument should not be indented with tab */
6344         addpCode2pBlock(pb, newpCodeAsmDir(NULL, bp1)); // inline directly, no process
6345
6346         bp1 = bp;
6347       } else
6348         bp++;
6349     }
6350   }
6351   if ((bp1 != bp) && *bp1)
6352     addpCode2pBlock(pb, newpCodeAsmDir(bp1, NULL)); // inline directly, no process
6353
6354   Safe_free(buffer);
6355
6356   _G.inLine -= (!options.asmpeep);
6357 }
6358
6359 /*-----------------------------------------------------------------*/
6360 /* genRRC - rotate right with carry                                */
6361 /*-----------------------------------------------------------------*/
6362 static void genRRC (iCode *ic)
6363 {
6364         operand *left , *result ;
6365         int size, offset = 0, same;
6366         
6367         FENTRY;
6368         /* rotate right with carry */
6369         left = IC_LEFT(ic);
6370         result=IC_RESULT(ic);
6371         aopOp (left,ic,FALSE);
6372         aopOp (result,ic,FALSE);
6373         
6374         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6375         
6376         same = pic14_sameRegs(AOP(result),AOP(left));
6377         
6378         size = AOP_SIZE(result);    
6379         
6380         /* get the lsb and put it into the carry */
6381         emitpcode(POC_RRFW, popGet(AOP(left),size-1));
6382         
6383         offset = 0 ;
6384         
6385         while(size--) {
6386                 
6387                 if(same) {
6388                         emitpcode(POC_RRF, popGet(AOP(left),offset));
6389                 } else {
6390                         emitpcode(POC_RRFW, popGet(AOP(left),offset));
6391                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6392                 }
6393                 
6394                 offset++;
6395         }
6396         
6397         freeAsmop(left,NULL,ic,TRUE);
6398         freeAsmop(result,NULL,ic,TRUE);
6399 }
6400
6401 /*-----------------------------------------------------------------*/
6402 /* genRLC - generate code for rotate left with carry               */
6403 /*-----------------------------------------------------------------*/
6404 static void genRLC (iCode *ic)
6405 {    
6406         operand *left , *result ;
6407         int size, offset = 0;
6408         int same;
6409         
6410         FENTRY;
6411         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6412         /* rotate right with carry */
6413         left = IC_LEFT(ic);
6414         result=IC_RESULT(ic);
6415         aopOp (left,ic,FALSE);
6416         aopOp (result,ic,FALSE);
6417         
6418         DEBUGpic14_AopType(__LINE__,left,NULL,result);
6419         
6420         same = pic14_sameRegs(AOP(result),AOP(left));
6421         
6422         /* move it to the result */
6423         size = AOP_SIZE(result);    
6424         
6425         /* get the msb and put it into the carry */
6426         emitpcode(POC_RLFW, popGet(AOP(left),size-1));
6427         
6428         offset = 0 ;
6429         
6430         while(size--) {
6431                 
6432                 if(same) {
6433                         emitpcode(POC_RLF, popGet(AOP(left),offset));
6434                 } else {
6435                         emitpcode(POC_RLFW, popGet(AOP(left),offset));
6436                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
6437                 }
6438                 
6439                 offset++;
6440         }
6441         
6442         
6443         freeAsmop(left,NULL,ic,TRUE);
6444         freeAsmop(result,NULL,ic,TRUE);
6445 }
6446
6447 /*-----------------------------------------------------------------*/
6448 /* genGetHbit - generates code get highest order bit               */
6449 /*-----------------------------------------------------------------*/
6450 static void genGetHbit (iCode *ic)
6451 {
6452         operand *left, *result;
6453         left = IC_LEFT(ic);
6454         result=IC_RESULT(ic);
6455         aopOp (left,ic,FALSE);
6456         aopOp (result,ic,FALSE);
6457         
6458         FENTRY;
6459         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6460         /* get the highest order byte into a */
6461         MOVA(aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6462         if(AOP_TYPE(result) == AOP_CRY){
6463                 pic14_emitcode("rlc","a");
6464                 pic14_outBitC(result);
6465         }
6466         else{
6467                 pic14_emitcode("rl","a");
6468                 pic14_emitcode("anl","a,#0x01");
6469                 pic14_outAcc(result);
6470         }
6471         
6472         
6473         freeAsmop(left,NULL,ic,TRUE);
6474         freeAsmop(result,NULL,ic,TRUE);
6475 }
6476
6477 /*-----------------------------------------------------------------*/
6478 /* AccLsh - shift left accumulator by known count                  */
6479 /* MARK: pic14 always rotates through CARRY!                       */
6480 /*-----------------------------------------------------------------*/
6481 static void AccLsh (pCodeOp *pcop,int shCount)
6482 {
6483         FENTRY;
6484         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6485         shCount &= 0x0007;              // shCount : 0..7
6486         switch(shCount){
6487         case 0 :
6488                 return;
6489                 break;
6490         case 1 :
6491                 emitCLRC;
6492                 emitpcode(POC_RLF,pcop);
6493                 return;
6494                 break;
6495         case 2 :
6496                 emitpcode(POC_RLF,pcop);
6497                 emitpcode(POC_RLF,pcop);
6498                 break;
6499         case 3 :
6500                 emitpcode(POC_RLF,pcop);
6501                 emitpcode(POC_RLF,pcop);
6502                 emitpcode(POC_RLF,pcop);
6503                 break;
6504         case 4 :
6505                 emitpcode(POC_SWAPF,pcop);
6506                 break;
6507         case 5 :
6508                 emitpcode(POC_SWAPF,pcop);
6509                 emitpcode(POC_RLF,pcop);
6510                 break;
6511         case 6 :
6512                 emitpcode(POC_SWAPF,pcop);
6513                 emitpcode(POC_RLF,pcop);
6514                 emitpcode(POC_RLF,pcop);
6515                 break;
6516         case 7 :
6517                 emitpcode(POC_RRFW,pcop);
6518                 emitpcode(POC_RRF,pcop);
6519                 break;
6520         }
6521         /* clear invalid bits */
6522         emitpcode(POC_MOVLW, popGetLit ((unsigned char)(~((1UL << shCount) - 1))));
6523         emitpcode(POC_ANDWF, pcop);
6524 }
6525
6526 /*-----------------------------------------------------------------*/
6527 /* AccRsh - shift right accumulator by known count                 */
6528 /* MARK: pic14 always rotates through CARRY!                       */
6529 /* maskmode - 0: leave invalid bits undefined (caller should mask) */
6530 /*            1: mask out invalid bits (zero-extend)               */
6531 /*            2: sign-extend result (pretty slow)                  */
6532 /*-----------------------------------------------------------------*/
6533 static void AccRsh (pCodeOp *pcop,int shCount, int mask_mode)
6534 {
6535         FENTRY;
6536         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6537         shCount &= 0x0007;              // shCount : 0..7
6538         switch(shCount){
6539         case 0 :
6540                 return;
6541                 break;
6542         case 1 :
6543                 /* load sign if needed */
6544                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6545                 else if (mask_mode == 1) emitCLRC;
6546                 emitpcode(POC_RRF,pcop);
6547                 return;
6548                 break;
6549         case 2 :
6550                 /* load sign if needed */
6551                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6552                 emitpcode(POC_RRF,pcop);
6553                 /* load sign if needed */
6554                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6555                 emitpcode(POC_RRF,pcop);
6556                 if (mask_mode == 2) return;
6557                 break;
6558         case 3 :
6559                 /* load sign if needed */
6560                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6561                 emitpcode(POC_RRF,pcop);
6562                 /* load sign if needed */
6563                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6564                 emitpcode(POC_RRF,pcop);
6565                 /* load sign if needed */
6566                 if (mask_mode == 2) emitpcode(POC_RLFW,pcop);
6567                 emitpcode(POC_RRF,pcop);
6568                 if (mask_mode == 2) return;
6569                 break;
6570         case 4 :
6571                 emitpcode(POC_SWAPF,pcop);
6572                 break;
6573         case 5 :
6574                 emitpcode(POC_SWAPF,pcop);
6575                 emitpcode(POC_RRF,pcop);
6576                 break;
6577         case 6 :
6578                 emitpcode(POC_SWAPF,pcop);
6579                 emitpcode(POC_RRF,pcop);
6580                 emitpcode(POC_RRF,pcop);
6581                 break;
6582         case 7 :
6583                 if (mask_mode == 2)
6584                 {
6585                         /* load sign */
6586                         emitpcode(POC_RLFW,pcop);
6587                         emitpcode(POC_CLRF,pcop);
6588                         emitSKPNC;
6589                         emitpcode(POC_COMF,pcop);
6590                         return;
6591                 } else {
6592                         emitpcode(POC_RLFW,pcop);
6593                         emitpcode(POC_RLF,pcop);
6594                 }
6595                 break;
6596         }
6597
6598         if (mask_mode == 0)
6599         {
6600                 /* leave invalid bits undefined */
6601                 return;
6602         }
6603         
6604         /* clear invalid bits -- zero-extend */
6605         emitpcode(POC_MOVLW, popGetLit (0x00ff >> shCount));
6606         emitpcode(POC_ANDWF, pcop);
6607
6608         if (mask_mode == 2) {
6609           /* sign-extend */
6610           emitpcode(POC_MOVLW, popGetLit (0x00ff << (8 - shCount)));
6611           emitpcode(POC_BTFSC, newpCodeOpBit (get_op(pcop,NULL,0), 7 - shCount ,0));
6612           emitpcode(POC_IORWF, pcop);
6613         }
6614 }
6615
6616 #if 0
6617 /*-----------------------------------------------------------------*/
6618 /* AccSRsh - signed right shift accumulator by known count                 */
6619 /*-----------------------------------------------------------------*/
6620 static void AccSRsh (int shCount)
6621 {
6622         symbol *tlbl ;
6623         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6624         if(shCount != 0){
6625                 if(shCount == 1){
6626                         pic14_emitcode("mov","c,acc.7");
6627                         pic14_emitcode("rrc","a");
6628                 } else if(shCount == 2){
6629                         pic14_emitcode("mov","c,acc.7");
6630                         pic14_emitcode("rrc","a");
6631                         pic14_emitcode("mov","c,acc.7");
6632                         pic14_emitcode("rrc","a");
6633                 } else {
6634                         tlbl = newiTempLabel(NULL);
6635                         /* rotate right accumulator */
6636                         AccRol(8 - shCount);
6637                         /* and kill the higher order bits */
6638                         pic14_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6639                         pic14_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6640                         pic14_emitcode("orl","a,#0x%02x",
6641                                 (unsigned char)~SRMask[shCount]);
6642                         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
6643                 }
6644         }
6645 }
6646
6647 /*-----------------------------------------------------------------*/
6648 /* shiftR1Left2Result - shift right one byte from left to result   */
6649 /*-----------------------------------------------------------------*/
6650 static void shiftR1Left2ResultSigned (operand *left, int offl,
6651                                                                           operand *result, int offr,
6652                                                                           int shCount)
6653 {
6654         int same;
6655         
6656         FENTRY;
6657         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6658         
6659         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6660         
6661         switch(shCount) {
6662         case 1:
6663                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6664                 if(same) 
6665                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6666                 else {
6667                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6668                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6669                 }
6670                 
6671                 break;
6672         case 2:
6673                 
6674                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6675                 if(same) 
6676                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6677                 else {
6678                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6679                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6680                 }
6681                 emitpcode(POC_RLFW, popGet(AOP(result),offr));
6682                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6683                 
6684                 break;
6685                 
6686         case 3:
6687                 if(same)
6688                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6689                 else {
6690                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6691                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6692                 }
6693                 
6694                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6695                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6696                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6697                 
6698                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6699                 emitpcode(POC_IORLW, popGetLit(0xe0));
6700                 
6701                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6702                 break;
6703                 
6704         case 4:
6705                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6706                 emitpcode(POC_ANDLW,  popGetLit(0x0f));
6707                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6708                 emitpcode(POC_IORLW,  popGetLit(0xf0));
6709                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6710                 break;
6711         case 5:
6712                 if(same) {
6713                         emitpcode(POC_SWAPF,  popGet(AOP(result),offr));
6714                 } else {
6715                         emitpcode(POC_SWAPFW,  popGet(AOP(left),offl));
6716                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6717                 }
6718                 emitpcode(POC_RRFW,   popGet(AOP(result),offr));
6719                 emitpcode(POC_ANDLW,  popGetLit(0x07));
6720                 emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6721                 emitpcode(POC_IORLW,  popGetLit(0xf8));
6722                 emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
6723                 break;
6724                 
6725         case 6:
6726                 if(same) {
6727                         emitpcode(POC_MOVLW, popGetLit(0x00));
6728                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6729                         emitpcode(POC_MOVLW, popGetLit(0xfe));
6730                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6731                         emitpcode(POC_IORLW, popGetLit(0x01));
6732                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6733                 } else {
6734                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6735                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6736                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6737                         emitpcode(POC_BTFSS, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6738                         emitpcode(POC_BCF,   newpCodeOpBit(aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6739                 }
6740                 break;
6741                 
6742         case 7:
6743                 if(same) {
6744                         emitpcode(POC_MOVLW, popGetLit(0x00));
6745                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6746                         emitpcode(POC_MOVLW, popGetLit(0xff));
6747                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6748                 } else {
6749                         emitpcode(POC_CLRF,  popGet(AOP(result),offr));
6750                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6751                         emitpcode(POC_DECF,  popGet(AOP(result),offr));
6752                 }
6753                 
6754         default:
6755                 break;
6756         }
6757 }
6758
6759 /*-----------------------------------------------------------------*/
6760 /* shiftR1Left2Result - shift right one byte from left to result   */
6761 /*-----------------------------------------------------------------*/
6762 static void shiftR1Left2Result (operand *left, int offl,
6763                                                                 operand *result, int offr,
6764                                                                 int shCount, int sign)
6765 {
6766         int same;
6767         
6768         FENTRY;
6769         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6770         
6771         same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6772         
6773         /* Copy the msb into the carry if signed. */
6774         if(sign) {
6775                 shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6776                 return;
6777         }
6778         
6779         
6780         
6781         switch(shCount) {
6782         case 1:
6783                 emitCLRC;
6784                 if(same) 
6785                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6786                 else {
6787                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6788                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6789                 }
6790                 break;
6791         case 2:
6792                 emitCLRC;
6793                 if(same) {
6794                         emitpcode(POC_RRF, popGet(AOP(result),offr));
6795                 } else {
6796                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
6797                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6798                 }
6799                 emitCLRC;
6800                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6801                 
6802                 break;
6803         case 3:
6804                 if(same)
6805                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
6806                 else {
6807                         emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6808                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6809                 }
6810                 
6811                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6812                 emitpcode(POC_RLFW,  popGet(AOP(result),offr));
6813                 emitpcode(POC_ANDLW, popGetLit(0x1f));
6814                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6815                 break;
6816                 
6817         case 4:
6818                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6819                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6820                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6821                 break;
6822                 
6823         case 5:
6824                 emitpcode(POC_SWAPFW, popGet(AOP(left),offl));
6825                 emitpcode(POC_ANDLW, popGetLit(0x0f));
6826                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6827                 emitCLRC;
6828                 emitpcode(POC_RRF, popGet(AOP(result),offr));
6829                 
6830                 break;
6831         case 6:
6832                 
6833                 emitpcode(POC_RLFW,  popGet(AOP(left),offl));
6834                 emitpcode(POC_ANDLW, popGetLit(0x80));
6835                 emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6836                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6837                 emitpcode(POC_RLF,   popGet(AOP(result),offr));
6838                 break;
6839                 
6840         case 7:
6841                 
6842                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6843                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6844                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6845                 
6846                 break;
6847                 
6848         default:
6849                 break;
6850         }
6851 }
6852
6853 /*-----------------------------------------------------------------*/
6854 /* shiftL1Left2Result - shift left one byte from left to result    */
6855 /*-----------------------------------------------------------------*/
6856 static void shiftL1Left2Result (operand *left, int offl,
6857                                                                 operand *result, int offr, int shCount)
6858 {
6859         int same;
6860         
6861         //    char *l;
6862         FENTRY;
6863         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6864         
6865         same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6866         DEBUGpic14_emitcode ("; ***","same =  %d",same);
6867         //    l = aopGet(AOP(left),offl,FALSE,FALSE);
6868         //    MOVA(l);
6869         /* shift left accumulator */
6870         //AccLsh(shCount); // don't comment out just yet...
6871         //    aopPut(AOP(result),"a",offr);
6872         
6873         switch(shCount) {
6874         case 1:
6875                 /* Shift left 1 bit position */
6876                 emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6877                 if(same) {
6878                         emitpcode(POC_ADDWF, popGet(AOP(left),offl));
6879                 } else {
6880                         emitpcode(POC_ADDFW, popGet(AOP(left),offl));
6881                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6882                 }
6883                 break;
6884         case 2:
6885                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6886                 emitpcode(POC_ANDLW,popGetLit(0x7e));
6887                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6888                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6889                 break;
6890         case 3:
6891                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
6892                 emitpcode(POC_ANDLW,popGetLit(0x3e));
6893                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6894                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6895                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6896                 break;
6897         case 4:
6898                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6899                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6900                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6901                 break;
6902         case 5:
6903                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6904                 emitpcode(POC_ANDLW, popGetLit(0xf0));
6905                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6906                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6907                 break;
6908         case 6:
6909                 emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
6910                 emitpcode(POC_ANDLW, popGetLit(0x30));
6911                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
6912                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
6913                 emitpcode(POC_RLF,  popGet(AOP(result),offr));
6914                 break;
6915         case 7:
6916                 emitpcode(POC_RRFW, popGet(AOP(left),offl));
6917                 emitpcode(POC_CLRF, popGet(AOP(result),offr));
6918                 emitpcode(POC_RRF,  popGet(AOP(result),offr));
6919                 break;
6920                 
6921         default:
6922                 DEBUGpic14_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6923         }
6924         
6925 }
6926 #endif
6927
6928 /*-----------------------------------------------------------------*/
6929 /* movLeft2Result - move byte from left to result                  */
6930 /*-----------------------------------------------------------------*/
6931 static void movLeft2Result (operand *left, int offl,
6932                                                         operand *result, int offr)
6933 {
6934         char *l;
6935         FENTRY;
6936         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6937         if(!pic14_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6938                 l = aopGet(AOP(left),offl,FALSE,FALSE);
6939                 
6940                 if (*l == '@' && (IS_AOP_PREG(result))) {
6941                         pic14_emitcode("mov","a,%s",l);
6942                         aopPut(AOP(result),"a",offr);
6943                 } else {
6944                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
6945                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
6946                 }
6947         }
6948 }
6949
6950 /*-----------------------------------------------------------------*/
6951 /* shiftLeft_Left2ResultLit - shift left by known count            */
6952 /*-----------------------------------------------------------------*/
6953
6954 static void shiftLeft_Left2ResultLit (operand *left, operand *result, int shCount)
6955 {
6956         int size, same, offr, i;
6957
6958         size = AOP_SIZE(left);
6959         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
6960         
6961         same = pic14_sameRegs (AOP(left), AOP(result));
6962         
6963         offr = shCount / 8;
6964         shCount = shCount & 0x07;
6965
6966         size -= offr;
6967
6968         switch (shCount)
6969         {
6970         case 0: /* takes 0 or 2N cycles (for offr==0) */
6971                 if (!same || offr) {
6972                         for (i=size-1; i >= 0; i--)
6973                                 movLeft2Result (left, i, result, offr + i);
6974                 } // if
6975                 break;
6976                 
6977         case 1: /* takes 1N+1 or 2N+1 cycles (or offr==0) */
6978                 if (same && offr) {
6979                         shiftLeft_Left2ResultLit (left, result, 8 * offr);
6980                         shiftLeft_Left2ResultLit (result, result, shCount);
6981                         return; /* prevent clearing result again */
6982                 } else {
6983                         emitCLRC;
6984                         for (i=0; i < size; i++) {
6985                                 if (same && !offr) {
6986                                         emitpcode (POC_RLF, popGet (AOP(left), i));
6987                                 } else {
6988                                         emitpcode (POC_RLFW, popGet (AOP(left), i));
6989                                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
6990                                 } // if
6991                         } // for
6992                 } // if (offr)
6993                 break;
6994                 
6995         case 4: /* takes 3+5(N-1) = 5N-2 cycles (for offr==0) */
6996                 /* works in-place/with offr as well */
6997                 emitpcode (POC_SWAPFW, popGet (AOP(left), size-1));
6998                 emitpcode (POC_ANDLW, popGetLit (0xF0));
6999                 emitpcode (POC_MOVWF, popGet(AOP(result), size-1+offr));
7000
7001                 for (i = size - 2; i >= 0; i--)
7002                 {
7003                         emitpcode (POC_SWAPFW, popGet (AOP(left), i));
7004                         emitpcode (POC_MOVWF, popGet (AOP(result), i + offr));
7005                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7006                         emitpcode (POC_IORWF, popGet (AOP(result), i + offr + 1));
7007                         emitpcode (POC_XORWF, popGet (AOP(result), i + offr));
7008                 } // for i
7009                 break;
7010                 
7011         case 7: /* takes 2(N-1)+3 = 2N+1 cycles */
7012                 /* works in-place/with offr as well */
7013                 emitpcode (POC_RRFW, popGet (AOP(left), size-1));
7014                 for (i = size-2; i >= 0; i--) {
7015                         emitpcode (POC_RRFW, popGet (AOP(left), i));
7016                         emitpcode (POC_MOVWF, popGet (AOP(result), offr + i + 1));
7017                 } // for i
7018                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7019                 emitpcode (POC_RRF, popGet (AOP(result), offr));
7020                 break;
7021         
7022         default:
7023                 shiftLeft_Left2ResultLit (left, result, offr * 8 + shCount-1);
7024                 shiftLeft_Left2ResultLit (result, result, 1);
7025                 return; /* prevent clearing result again */
7026                 break;
7027         } // switch
7028
7029         while (0 < offr--)
7030         {
7031                 emitpcode (POC_CLRF, popGet (AOP(result), offr));
7032         } // while
7033 }
7034
7035 /*-----------------------------------------------------------------*/
7036 /* shiftRight_Left2ResultLit - shift right by known count          */
7037 /*-----------------------------------------------------------------*/
7038
7039 static void shiftRight_Left2ResultLit (operand *left, operand *result, int shCount, int sign)
7040 {
7041         int size, same, offr, i;
7042
7043         size = AOP_SIZE(left);
7044         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7045         
7046         same = pic14_sameRegs (AOP(left), AOP(result));
7047         
7048         offr = shCount / 8;
7049         shCount = shCount & 0x07;
7050
7051         size -= offr;
7052
7053         if (size)
7054         {
7055                 switch (shCount)
7056                 {
7057                 case 0: /* takes 0 or 2N cycles (for offr==0) */
7058                         if (!same || offr) {
7059                                 for (i=0; i < size; i++)
7060                                         movLeft2Result (left, i + offr, result, i);
7061                         } // if
7062                         break;
7063                         
7064                 case 1: /* takes 1N+1(3) or 2N+1(3) cycles (or offr==0) */
7065                         emitpComment ("%s:%d: shCount=%d, size=%d, sign=%d, same=%d, offr=%d", __FUNCTION__, __LINE__, shCount, size, sign, same, offr);
7066                         if (same && offr) {
7067                                 shiftRight_Left2ResultLit (left, result, 8 * offr, sign);
7068                                 shiftRight_Left2ResultLit (result, result, shCount, sign);
7069                                 return; /* prevent sign-extending result again */
7070                         } else {
7071                                 emitCLRC;
7072                                 if (sign) {
7073                                         emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(left), AOP_SIZE(left)-1, FALSE, FALSE), 7, 0));
7074                                         emitSETC;
7075                                 }
7076                                 for (i = size-1; i >= 0; i--) {
7077                                         if (same && !offr) {
7078                                                 emitpcode (POC_RRF, popGet (AOP(left), i));
7079                                         } else {
7080                                                 emitpcode (POC_RRFW, popGet (AOP(left), i + offr));
7081                                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7082                                         }
7083                                 } // for i
7084                         } // if (offr)
7085                         break;
7086                         
7087                 case 4: /* takes 3(6)+5(N-1) = 5N-2(+1) cycles (for offr==0) */
7088                         /* works in-place/with offr as well */
7089                         emitpcode (POC_SWAPFW, popGet (AOP(left), offr));
7090                         emitpcode (POC_ANDLW, popGetLit (0x0F));
7091                         emitpcode (POC_MOVWF, popGet(AOP(result), 0));
7092
7093                         for (i = 1; i < size; i++)
7094                         {
7095                                 emitpcode (POC_SWAPFW, popGet (AOP(left), i + offr));
7096                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7097                                 emitpcode (POC_ANDLW, popGetLit (0xF0));
7098                                 emitpcode (POC_IORWF, popGet (AOP(result), i - 1));
7099                                 emitpcode (POC_XORWF, popGet (AOP(result), i));
7100                         } // for i
7101
7102                         if (sign)
7103                         {
7104                                 emitpcode (POC_MOVLW, popGetLit (0xF0));
7105                                 emitpcode (POC_BTFSC, newpCodeOpBit (aopGet (AOP(result), size-1, FALSE, FALSE), 3, 0));
7106                                 emitpcode (POC_IORWF, popGet (AOP(result), size-1));
7107                         } // if
7108                         break;
7109                         
7110                 case 7: /* takes 2(N-1)+3(4) = 2N+1(2) cycles */
7111                         /* works in-place/with offr as well */
7112                         emitpcode (POC_RLFW, popGet (AOP(left), offr));
7113                         for (i = 0; i < size-1; i++) {
7114                                 emitpcode (POC_RLFW, popGet (AOP(left), offr + i + 1));
7115                                 emitpcode (POC_MOVWF, popGet (AOP(result), i));
7116                         } // for i
7117                         emitpcode (POC_CLRF, popGet (AOP(result), size-1));
7118                         if (!sign) {
7119                                 emitpcode (POC_RLF, popGet (AOP(result), size-1));
7120                         } else {
7121                                 emitSKPNC;
7122                                 emitpcode (POC_DECF, popGet (AOP(result), size-1));
7123                         }
7124                         break;
7125                 
7126                 default:
7127                         shiftRight_Left2ResultLit (left, result, offr * 8 + shCount-1, sign);
7128                         shiftRight_Left2ResultLit (result, result, 1, sign);
7129                         return; /* prevent sign extending result again */
7130                         break;
7131                 } // switch
7132         } // if
7133
7134         addSign (result, size, sign);
7135 }
7136
7137 #if 0
7138 /*-----------------------------------------------------------------*/
7139 /* shiftL2Left2Result - shift left two bytes from left to result   */
7140 /*-----------------------------------------------------------------*/
7141 static void shiftL2Left2Result (operand *left, int offl,
7142                                                                 operand *result, int offr, int shCount)
7143 {
7144         FENTRY;
7145         
7146         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7147         
7148         if(pic14_sameRegs(AOP(result), AOP(left))) {
7149                 switch(shCount) {
7150                 case 0:
7151                         break;
7152                 case 1:
7153                 case 2:
7154                 case 3:
7155                         
7156                         emitpcode(POC_MOVFW,popGet(AOP(result),offr));
7157                         emitpcode(POC_ADDWF,popGet(AOP(result),offr));
7158                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7159                         
7160                         while(--shCount) {
7161                                 emitCLRC;
7162                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7163                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7164                         }
7165                         
7166                         break;
7167                 case 4:
7168                 case 5:
7169                         emitpcode(POC_MOVLW, popGetLit(0x0f));
7170                         emitpcode(POC_ANDWF, popGet(AOP(result),offr+MSB16));
7171                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7172                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7173                         emitpcode(POC_ANDFW, popGet(AOP(result),offr));
7174                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7175                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7176                         if(shCount >=5) {
7177                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7178                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7179                         }
7180                         break;
7181                 case 6:
7182                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7183                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7184                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7185                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7186                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7187                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7188                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7189                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7190                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7191                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7192                         break;
7193                 case 7:
7194                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7195                         emitpcode(POC_RRFW, popGet(AOP(result),offr));
7196                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7197                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7198                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7199                 }
7200                 
7201         } else {
7202                 switch(shCount) {
7203                 case 0:
7204                         break;
7205                 case 1:
7206                 case 2:
7207                 case 3:
7208                 /* note, use a mov/add for the shift since the mov has a
7209                         chance of getting optimized out */
7210                         emitpcode(POC_MOVFW, popGet(AOP(left),offl));
7211                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7212                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7213                         emitpcode(POC_RLFW,  popGet(AOP(left),offl+MSB16));
7214                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7215                         
7216                         while(--shCount) {
7217                                 emitCLRC;
7218                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7219                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7220                         }
7221                         break;
7222                         
7223                 case 4:
7224                 case 5:
7225                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7226                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7227                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7228                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7229                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7230                         emitpcode(POC_ANDLW, popGetLit(0xF0));
7231                         emitpcode(POC_XORWF, popGet(AOP(result),offr));
7232                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7233                         
7234                         
7235                         if(shCount == 5) {
7236                                 emitpcode(POC_RLF, popGet(AOP(result),offr));
7237                                 emitpcode(POC_RLF, popGet(AOP(result),offr+MSB16));
7238                         }
7239                         break;
7240                 case 6:
7241                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7242                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7243                         emitpcode(POC_RRFW, popGet(AOP(result),offl));
7244                         emitpcode(POC_MOVWF,  popGet(AOP(result),offr));
7245                         
7246                         emitpcode(POC_RRF,  popGet(AOP(result),offr+MSB16));
7247                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7248                         emitpcode(POC_RRFW, popGet(AOP(result),offr+MSB16));
7249                         emitpcode(POC_ANDLW,popGetLit(0xc0));
7250                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7251                         emitpcode(POC_XORWF,popGet(AOP(result),offr));
7252                         emitpcode(POC_XORFW,popGet(AOP(result),offr));
7253                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7254                         break;
7255                 case 7:
7256                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7257                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7258                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7259                         emitpcode(POC_CLRF, popGet(AOP(result),offr));
7260                         emitpcode(POC_RRF,  popGet(AOP(result),offr));
7261                 }
7262         }
7263         
7264 }
7265
7266 /*-----------------------------------------------------------------*/
7267 /* shiftR2Left2Result - shift right two bytes from left to result  */
7268 /*-----------------------------------------------------------------*/
7269 static void shiftR2Left2Result (operand *left, int offl,
7270                                                                 operand *result, int offr,
7271                                                                 int shCount, int sign)
7272 {
7273         int same=0;
7274         
7275         FENTRY;
7276         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7277         same = pic14_sameRegs(AOP(result), AOP(left));
7278         
7279         if(same && ((offl + MSB16) == offr)){
7280                 same=1;
7281                 /* don't crash result[offr] */
7282                 MOVA(aopGet(AOP(left),offl,FALSE,FALSE));
7283                 pic14_emitcode("xch","a,%s", aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7284         }
7285         /* else {
7286         movLeft2Result(left,offl, result, offr);
7287         MOVA(aopGet(AOP(left),offl+MSB16,FALSE,FALSE));
7288         }
7289         */
7290         /* a:x >> shCount (x = lsb(result))*/
7291         /*
7292         if(sign)
7293         AccAXRshS( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7294         else {
7295         AccAXRsh( aopGet(AOP(result),offr,FALSE,FALSE) , shCount);
7296         */
7297         switch(shCount) {
7298         case 0:
7299                 break;
7300         case 1:
7301         case 2:
7302         case 3:
7303                 if(sign)
7304                         emitpcode(POC_RLFW,popGet(AOP(left),offl+MSB16));
7305                 else
7306                         emitCLRC;
7307                 
7308                 if(same) {
7309                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7310                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7311                 } else {
7312                         emitpcode(POC_RRFW, popGet(AOP(left),offl+MSB16));
7313                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7314                         emitpcode(POC_RRFW, popGet(AOP(left),offl));
7315                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7316                 }
7317                 
7318                 while(--shCount) {
7319                         if(sign)
7320                                 emitpcode(POC_RLFW,popGet(AOP(result),offr+MSB16));
7321                         else
7322                                 emitCLRC;
7323                         emitpcode(POC_RRF,popGet(AOP(result),offr+MSB16));
7324                         emitpcode(POC_RRF,popGet(AOP(result),offr));
7325                 }
7326                 break;
7327         case 4:
7328         case 5:
7329                 if(same) {
7330                         
7331                         emitpcode(POC_MOVLW, popGetLit(0xf0));
7332                         emitpcode(POC_ANDWF, popGet(AOP(result),offr));
7333                         emitpcode(POC_SWAPF, popGet(AOP(result),offr));
7334                         
7335                         emitpcode(POC_SWAPF, popGet(AOP(result),offr+MSB16));
7336                         emitpcode(POC_ANDFW, popGet(AOP(result),offr+MSB16));
7337                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7338                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7339                 } else {
7340                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl));
7341                         emitpcode(POC_ANDLW, popGetLit(0x0f));
7342                         emitpcode(POC_MOVWF, popGet(AOP(result),offr));
7343                         
7344                         emitpcode(POC_SWAPFW,popGet(AOP(left),offl+MSB16));
7345                         emitpcode(POC_MOVWF, popGet(AOP(result),offr+MSB16));
7346                         emitpcode(POC_ANDLW, popGetLit(0xf0));
7347                         emitpcode(POC_XORWF, popGet(AOP(result),offr+MSB16));
7348                         emitpcode(POC_ADDWF, popGet(AOP(result),offr));
7349                 }
7350                 
7351                 if(shCount >=5) {
7352                         emitpcode(POC_RRF, popGet(AOP(result),offr+MSB16));
7353                         emitpcode(POC_RRF, popGet(AOP(result),offr));
7354                 }
7355                 
7356                 if(sign) {
7357                         emitpcode(POC_MOVLW, popGetLit(0xf0 + (shCount-4)*8 ));
7358                         emitpcode(POC_BTFSC, 
7359                                 newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7360                         emitpcode(POC_ADDWF, popGet(AOP(result),offr+MSB16));
7361                 }
7362                 
7363                 break;
7364                 
7365         case 6:
7366                 if(same) {
7367                         
7368                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7369                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7370                         
7371                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7372                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7373                         emitpcode(POC_RLFW, popGet(AOP(result),offr));
7374                         emitpcode(POC_ANDLW,popGetLit(0x03));
7375                         if(sign) {
7376                                 emitpcode(POC_BTFSC, 
7377                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7378                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7379                         }
7380                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7381                         emitpcode(POC_XORWF,popGet(AOP(result),offr+MSB16));
7382                         emitpcode(POC_XORFW,popGet(AOP(result),offr+MSB16));
7383                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7384                 } else {
7385                         emitpcode(POC_RLFW, popGet(AOP(left),offl));
7386                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7387                         emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7388                         emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7389                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7390                         emitpcode(POC_RLF,  popGet(AOP(result),offr));
7391                         emitpcode(POC_RLFW, popGet(AOP(result),offr+MSB16));
7392                         emitpcode(POC_ANDLW,popGetLit(0x03));
7393                         if(sign) {
7394                                 emitpcode(POC_BTFSC, 
7395                                         newpCodeOpBit(aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7396                                 emitpcode(POC_IORLW,popGetLit(0xfc));
7397                         }
7398                         emitpcode(POC_MOVWF,popGet(AOP(result),offr+MSB16));
7399                         //emitpcode(POC_RLF,  popGet(AOP(result),offr));
7400                         
7401                         
7402                 }
7403                 
7404                 break;
7405         case 7:
7406                 emitpcode(POC_RLFW, popGet(AOP(left),offl));
7407                 emitpcode(POC_RLFW, popGet(AOP(left),offl+MSB16));
7408                 emitpcode(POC_MOVWF,popGet(AOP(result),offr));
7409                 emitpcode(POC_CLRF, popGet(AOP(result),offr+MSB16));
7410                 if(sign) {
7411                         emitSKPNC;
7412                         emitpcode(POC_DECF, popGet(AOP(result),offr+MSB16));
7413                 } else 
7414                         emitpcode(POC_RLF,  popGet(AOP(result),offr+MSB16));
7415   }
7416 }
7417
7418 /*-----------------------------------------------------------------*/
7419 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7420 /*-----------------------------------------------------------------*/
7421 static void shiftLLeftOrResult (operand *left, int offl,
7422                                                                 operand *result, int offr, int shCount)
7423 {
7424         FENTRY;
7425         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7426         
7427         /* shift left accumulator */
7428         AccLsh(left,offl,shCount);
7429         /* or with result */
7430         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7431         assert ( !"broken (modifies left, fails for left==result))" );
7432 }
7433
7434 /*-----------------------------------------------------------------*/
7435 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7436 /*-----------------------------------------------------------------*/
7437 static void shiftRLeftOrResult (operand *left, int offl,
7438                                                                 operand *result, int offr, int shCount)
7439 {
7440         FENTRY;
7441         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7442         
7443         /* shift right accumulator */
7444         AccRsh(left,offl,shCount);
7445         /* or with result */
7446         emitpcode (POC_IORWF, popGet (AOP(result), offr));
7447         assert ( !"broken (modifies left, fails for left==result))" );
7448 }
7449
7450 /*-----------------------------------------------------------------*/
7451 /* genlshOne - left shift a one byte quantity by known count       */
7452 /*-----------------------------------------------------------------*/
7453 static void genlshOne (operand *result, operand *left, int shCount)
7454 {       
7455         FENTRY;
7456         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7457         shiftL1Left2Result(left, LSB, result, LSB, shCount);
7458 }
7459
7460 /*-----------------------------------------------------------------*/
7461 /* genlshTwo - left shift two bytes by known amount != 0           */
7462 /*-----------------------------------------------------------------*/
7463 static void genlshTwo (operand *result,operand *left, int shCount)
7464 {
7465         int size;
7466         
7467         FENTRY;
7468         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7469         size = pic14_getDataSize(result);
7470         
7471         /* if shCount >= 8 */
7472         if (shCount >= 8) {
7473                 shCount -= 8 ;
7474                 
7475                 if (size > 1){
7476                         if (shCount)
7477                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7478                         else 
7479                                 movLeft2Result(left, LSB, result, MSB16);
7480                 }
7481                 emitpcode(POC_CLRF,popGet(AOP(result),LSB));
7482         }
7483         
7484         /*  1 <= shCount <= 7 */
7485         else {  
7486                 if(size == 1)
7487                         shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7488                 else 
7489                         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7490         }
7491 }
7492
7493 /*-----------------------------------------------------------------*/
7494 /* shiftLLong - shift left one long from left to result            */
7495 /* offl = LSB or MSB16                                             */
7496 /*-----------------------------------------------------------------*/
7497 static void shiftLLong (operand *left, operand *result, int offr )
7498 {
7499         char *l;
7500         int size = AOP_SIZE(result);
7501         
7502         FENTRY;
7503         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7504         if(size >= LSB+offr){
7505                 l = aopGet(AOP(left),LSB,FALSE,FALSE);
7506                 MOVA(l);
7507                 pic14_emitcode("add","a,acc");
7508                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7509                         size >= MSB16+offr && offr != LSB )
7510                         pic14_emitcode("xch","a,%s",
7511                         aopGet(AOP(left),LSB+offr,FALSE,FALSE));
7512                 else      
7513                         aopPut(AOP(result),"a",LSB+offr);
7514         }
7515         
7516         if(size >= MSB16+offr){
7517                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB16+offr && offr != LSB) ) {
7518                         l = aopGet(AOP(left),MSB16,FALSE,FALSE);
7519                         MOVA(l);
7520                 }
7521                 pic14_emitcode("rlc","a");
7522                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7523                         size >= MSB24+offr && offr != LSB)
7524                         pic14_emitcode("xch","a,%s",
7525                         aopGet(AOP(left),MSB16+offr,FALSE,FALSE));
7526                 else      
7527                         aopPut(AOP(result),"a",MSB16+offr);
7528         }
7529         
7530         if(size >= MSB24+offr){
7531                 if (!(pic14_sameRegs(AOP(left),AOP(left)) && size >= MSB24+offr && offr != LSB)) {
7532                         l = aopGet(AOP(left),MSB24,FALSE,FALSE);
7533                         MOVA(l);
7534                 }
7535                 pic14_emitcode("rlc","a");
7536                 if (pic14_sameRegs(AOP(left),AOP(result)) && 
7537                         size >= MSB32+offr && offr != LSB )
7538                         pic14_emitcode("xch","a,%s",
7539                         aopGet(AOP(left),MSB24+offr,FALSE,FALSE));
7540                 else      
7541                         aopPut(AOP(result),"a",MSB24+offr);
7542         }
7543         
7544         if(size > MSB32+offr){
7545                 if (!(pic14_sameRegs(AOP(result),AOP(left)) && size >= MSB32+offr && offr != LSB)) {
7546                         l = aopGet(AOP(left),MSB32,FALSE,FALSE);
7547                         MOVA(l);  
7548                 }
7549                 pic14_emitcode("rlc","a");
7550                 aopPut(AOP(result),"a",MSB32+offr);
7551         }
7552         if(offr != LSB)
7553                 aopPut(AOP(result),zero,LSB);       
7554 }
7555
7556 /*-----------------------------------------------------------------*/
7557 /* genlshFour - shift four byte by a known amount != 0             */
7558 /*-----------------------------------------------------------------*/
7559 static void genlshFour (operand *result, operand *left, int shCount)
7560 {
7561         int size;
7562         
7563         FENTRY;
7564         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7565         size = AOP_SIZE(result);
7566         
7567         /* if shifting more that 3 bytes */
7568         if (shCount >= 24 ) {
7569                 shCount -= 24;
7570                 if (shCount)
7571                 /* lowest order of left goes to the highest
7572                 order of the destination */
7573                 shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7574                 else
7575                         movLeft2Result(left, LSB, result, MSB32);
7576                 aopPut(AOP(result),zero,LSB);
7577                 aopPut(AOP(result),zero,MSB16);
7578                 aopPut(AOP(result),zero,MSB32);
7579                 return;
7580         }
7581         
7582         /* more than two bytes */
7583         else if ( shCount >= 16 ) {
7584                 /* lower order two bytes goes to higher order two bytes */
7585                 shCount -= 16;
7586                 /* if some more remaining */
7587                 if (shCount)
7588                         shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7589                 else {
7590                         movLeft2Result(left, MSB16, result, MSB32);
7591                         movLeft2Result(left, LSB, result, MSB24);
7592                 }
7593                 aopPut(AOP(result),zero,MSB16);
7594                 aopPut(AOP(result),zero,LSB);
7595                 return;
7596         }    
7597         
7598         /* if more than 1 byte */
7599         else if ( shCount >= 8 ) {
7600                 /* lower order three bytes goes to higher order  three bytes */
7601                 shCount -= 8;
7602                 if(size == 2){
7603                         if(shCount)
7604                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7605                         else
7606                                 movLeft2Result(left, LSB, result, MSB16);
7607                 }
7608                 else{   /* size = 4 */
7609                         if(shCount == 0){
7610                                 movLeft2Result(left, MSB24, result, MSB32);
7611                                 movLeft2Result(left, MSB16, result, MSB24);
7612                                 movLeft2Result(left, LSB, result, MSB16);
7613                                 aopPut(AOP(result),zero,LSB);
7614                         }
7615                         else if(shCount == 1)
7616                                 shiftLLong(left, result, MSB16);
7617                         else{
7618                                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7619                                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7620                                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7621                                 aopPut(AOP(result),zero,LSB);
7622                         }
7623                 }
7624         }
7625         
7626         /* 1 <= shCount <= 7 */
7627         else if(shCount <= 2){
7628                 shiftLLong(left, result, LSB);
7629                 if(shCount == 2)
7630                         shiftLLong(result, result, LSB);
7631         }
7632         /* 3 <= shCount <= 7, optimize */
7633         else{
7634                 shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7635                 shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7636                 shiftL2Left2Result(left, LSB, result, LSB, shCount);
7637         }
7638 }
7639 #endif
7640
7641 #if 0
7642 /*-----------------------------------------------------------------*/
7643 /* genLeftShiftLiteral - left shifting by known count              */
7644 /*-----------------------------------------------------------------*/
7645 static void genLeftShiftLiteral (operand *left,
7646                                                                  operand *right,
7647                                                                  operand *result,
7648                                                                  iCode *ic)
7649 {    
7650         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7651         //int size;
7652         
7653         FENTRY;
7654         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7655         freeAsmop(right,NULL,ic,TRUE);
7656         
7657         aopOp(left,ic,FALSE);
7658         aopOp(result,ic,FALSE);
7659
7660         size = getSize(operandType(result));
7661         
7662 #if VIEW_SIZE
7663         pic14_emitcode("; shift left ","result %d, left %d",size,
7664                 AOP_SIZE(left));
7665 #endif
7666         
7667         /* I suppose that the left size >= result size */
7668         if(shCount == 0){
7669                 while(size--){
7670                         movLeft2Result(left, size, result, size);
7671                 }
7672         }
7673         
7674         else if(shCount >= (size * 8))
7675                 while(size--)
7676                         aopPut(AOP(result),zero,size);
7677                 else{
7678                         switch (size) {
7679                         case 1:
7680                                 genlshOne (result,left,shCount);
7681                                 break;
7682                                 
7683                         case 2:
7684                         case 3:
7685                                 genlshTwo (result,left,shCount);
7686                                 break;
7687                                 
7688                         case 4:
7689                                 genlshFour (result,left,shCount);
7690                                 break;
7691                         }
7692                 }
7693                 freeAsmop(left,NULL,ic,TRUE);
7694                 freeAsmop(result,NULL,ic,TRUE);
7695 }
7696 #endif
7697
7698 /*-----------------------------------------------------------------*
7699 * genMultiAsm - repeat assembly instruction for size of register.
7700 * if endian == 1, then the high byte (i.e base address + size of 
7701 * register) is used first else the low byte is used first;
7702 *-----------------------------------------------------------------*/
7703 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7704 {
7705         
7706         int offset = 0;
7707         
7708         FENTRY;
7709         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7710         
7711         if(!reg)
7712                 return;
7713         
7714         if(!endian) {
7715                 endian = 1;
7716         } else {
7717                 endian = -1;
7718                 offset = size-1;
7719         }
7720         
7721         while(size--) {
7722                 emitpcode(poc,    popGet(AOP(reg),offset));
7723                 offset += endian;
7724         }
7725         
7726 }
7727
7728 #if 0
7729 /*-----------------------------------------------------------------*/
7730 /* genLeftShift - generates code for left shifting                 */
7731 /*-----------------------------------------------------------------*/
7732 static void genLeftShift (iCode *ic)
7733 {
7734         operand *left,*right, *result;
7735         int size, offset;
7736         unsigned long lit = 0L;
7737         char *l;
7738         symbol *tlbl , *tlbl1;
7739         pCodeOp *pctemp;
7740         
7741         FENTRY;
7742         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7743         
7744         right = IC_RIGHT(ic);
7745         left  = IC_LEFT(ic);
7746         result = IC_RESULT(ic);
7747         
7748         aopOp(right,ic,FALSE);
7749         aopOp(left,ic,FALSE);
7750         aopOp(result,ic,FALSE);
7751         
7752         
7753         /* if the shift count is known then do it 
7754         as efficiently as possible */
7755         if (AOP_TYPE(right) == AOP_LIT) {
7756                 shiftLeft_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit));
7757                 return ;
7758         }
7759         
7760         /* shift count is unknown then we have to form 
7761         a loop get the loop count in B : Note: we take
7762         only the lower order byte since shifting
7763         more that 32 bits make no sense anyway, ( the
7764         largest size of an object can be only 32 bits ) */  
7765         
7766         /* this code fails for RIGHT == RESULT */
7767         assert (!pic14_sameRegs (AOP(right), AOP(result)));
7768         
7769         /* now move the left to the result if they are not the
7770         same */
7771         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
7772                 AOP_SIZE(result) > 1) {
7773                 
7774                 size = AOP_SIZE(result);
7775                 offset=0;
7776                 while (size--) {
7777                         l = aopGet(AOP(left),offset,FALSE,TRUE);
7778                         if (*l == '@' && (IS_AOP_PREG(result))) {
7779                                 
7780                                 pic14_emitcode("mov","a,%s",l);
7781                                 aopPut(AOP(result),"a",offset);
7782                         } else {
7783                                 emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
7784                                 emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
7785                                 //aopPut(AOP(result),l,offset);
7786                         }
7787                         offset++;
7788                 }
7789         }
7790         
7791         if(AOP_TYPE(left) == AOP_LIT)
7792                 lit = (unsigned long)floatFromVal (AOP(left)->aopu.aop_lit);
7793
7794         size = AOP_SIZE(result);
7795         
7796         /* if it is only one byte then */
7797         if (size == 1) {
7798                 if(optimized_for_speed && AOP_TYPE(left)!=AOP_LIT) {
7799                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
7800                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
7801                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),2,0));
7802                         emitpcode(POC_MOVFW,  popGet(AOP(left),0));
7803                         emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7804                         emitpcode(POC_BTFSS,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),0,0));
7805                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7806                         emitpcode(POC_RLFW,   popGet(AOP(result),0));
7807                         emitpcode(POC_ANDLW,  popGetLit(0xfe));
7808                         emitpcode(POC_ADDFW,  popGet(AOP(result),0));
7809                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),1,0));
7810                         emitpcode(POC_ADDWF,  popGet(AOP(result),0));
7811                 } else {
7812                         
7813                         tlbl = newiTempLabel(NULL);
7814                         if (!pic14_sameRegs(AOP(left),AOP(result))) {
7815                                 mov2w (AOP(left), 0);
7816                                 emitpcode(POC_MOVWF,  popGet(AOP(result),0));
7817                         }
7818                         
7819                         emitpcode(POC_COMFW,  popGet(AOP(right),0));
7820                         emitpcode(POC_RRF,    popGet(AOP(result),0));
7821                         emitpLabel(tlbl->key);
7822                         emitpcode(POC_RLF,    popGet(AOP(result),0));
7823                         emitpcode(POC_ADDLW,  popGetLit(1));
7824                         emitSKPC;
7825                         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7826                 }
7827                 goto release ;
7828         }
7829         
7830         if (pic14_sameRegs(AOP(left),AOP(result))) {
7831                 
7832                 tlbl = newiTempLabel(NULL);
7833                 emitpcode(POC_COMFW,  popGet(AOP(right),0));
7834                 genMultiAsm(POC_RRF, result, size,1);
7835                 emitpLabel(tlbl->key);
7836                 genMultiAsm(POC_RLF, result, size,0);
7837                 emitpcode(POC_ADDLW,  popGetLit(1));
7838                 emitSKPC;
7839                 emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7840                 goto release;
7841         }
7842         
7843         //tlbl = newiTempLabel(NULL);
7844         //offset = 0 ;   
7845         //tlbl1 = newiTempLabel(NULL);
7846         
7847         //reAdjustPreg(AOP(result));    
7848         
7849         //pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7850         //pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
7851         //l = aopGet(AOP(result),offset,FALSE,FALSE);
7852         //MOVA(l);
7853         //pic14_emitcode("add","a,acc");         
7854         //aopPut(AOP(result),"a",offset++);
7855         //while (--size) {
7856         //  l = aopGet(AOP(result),offset,FALSE,FALSE);
7857         //  MOVA(l);
7858         //  pic14_emitcode("rlc","a");         
7859         //  aopPut(AOP(result),"a",offset++);
7860         //}
7861         //reAdjustPreg(AOP(result));
7862         
7863         //pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
7864         //pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7865         
7866         
7867         tlbl = newiTempLabel(NULL);
7868         tlbl1= newiTempLabel(NULL);
7869         
7870         size = AOP_SIZE(result);
7871         offset = 1;
7872         
7873         pctemp = popGetTempReg();  /* grab a temporary working register. */
7874         
7875         emitpcode(POC_MOVFW, popGet(AOP(right),0));
7876         
7877         /* offset should be 0, 1 or 3 */
7878         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
7879         emitSKPNZ;
7880         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
7881         
7882         emitpcode(POC_MOVWF, pctemp);
7883         
7884         
7885         emitpLabel(tlbl->key);
7886         
7887         emitCLRC;
7888         emitpcode(POC_RLF,  popGet(AOP(result),0));
7889         while(--size)
7890                 emitpcode(POC_RLF,   popGet(AOP(result),offset++));
7891         
7892         emitpcode(POC_DECFSZ,  pctemp);
7893         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
7894         emitpLabel(tlbl1->key);
7895         
7896         popReleaseTempReg(pctemp);
7897         
7898         
7899 release:
7900         freeAsmop (right,NULL,ic,TRUE);
7901         freeAsmop(left,NULL,ic,TRUE);
7902         freeAsmop(result,NULL,ic,TRUE);
7903 }
7904 #endif
7905
7906 #if 0
7907 /*-----------------------------------------------------------------*/
7908 /* genrshOne - right shift a one byte quantity by known count      */
7909 /*-----------------------------------------------------------------*/
7910 static void genrshOne (operand *result, operand *left,
7911                                            int shCount, int sign)
7912 {
7913         FENTRY;
7914         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7915         shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7916 }
7917
7918 /*-----------------------------------------------------------------*/
7919 /* genrshTwo - right shift two bytes by known amount != 0          */
7920 /*-----------------------------------------------------------------*/
7921 static void genrshTwo (operand *result,operand *left,
7922                                            int shCount, int sign)
7923 {
7924         FENTRY;
7925         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7926         /* if shCount >= 8 */
7927         if (shCount >= 8) {
7928                 shCount -= 8 ;
7929                 if (shCount)
7930                         shiftR1Left2Result(left, MSB16, result, LSB,
7931                         shCount, sign);
7932                 else
7933                         movLeft2Result(left, MSB16, result, LSB);
7934                 
7935                 emitpcode(POC_CLRF,popGet(AOP(result),MSB16));
7936                 
7937                 if(sign) {
7938                         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7939                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
7940                 }
7941         }
7942         
7943         /*  1 <= shCount <= 7 */
7944         else
7945                 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7946 }
7947
7948 /*-----------------------------------------------------------------*/
7949 /* shiftRLong - shift right one long from left to result           */
7950 /* offl = LSB or MSB16                                             */
7951 /*-----------------------------------------------------------------*/
7952 static void shiftRLong (operand *left, int offl,
7953                                                 operand *result, int sign)
7954 {
7955         int size, same;
7956         
7957         FENTRY;
7958         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7959         
7960         size = AOP_SIZE(left);
7961         if (AOP_SIZE(result) < size) size = AOP_SIZE(result);
7962         
7963         if (sign)
7964                 emitpcode (POC_RLFW, popGet (AOP(left), AOP_SIZE(left)-1));
7965         else
7966                 emitCLRC;
7967
7968         assert (offl >= 0 && offl < size);
7969
7970         same = pic14_sameRegs (AOP(left), AOP(result));
7971
7972         /* perform the shift */
7973         while (size--)
7974         {
7975                 if (same && !offl) {
7976                         emitpcode (POC_RRF, popGet (AOP(result), size));
7977                 } else {
7978                         emitpcode (POC_RRFW, popGet (AOP(left), size));
7979                         emitpcode (POC_MOVWF, popGet (AOP(result), size-offl));
7980                 }
7981         } // while
7982
7983         addSign (result, AOP_SIZE(left) - offl, sign);
7984 }
7985
7986 /*-----------------------------------------------------------------*/
7987 /* genrshFour - shift four byte by a known amount != 0             */
7988 /*-----------------------------------------------------------------*/
7989 static void genrshFour (operand *result, operand *left,
7990                                                 int shCount, int sign)
7991 {
7992         FENTRY;
7993         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7994         /* if shifting more that 3 bytes */
7995         if(shCount >= 24 ) {
7996                 shCount -= 24;
7997                 if(shCount)
7998                         shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7999                 else
8000                         movLeft2Result(left, MSB32, result, LSB);
8001                 
8002                 addSign(result, MSB16, sign);
8003         }
8004         else if(shCount >= 16){
8005                 shCount -= 16;
8006                 if(shCount)
8007                         shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8008                 else{
8009                         movLeft2Result(left, MSB24, result, LSB);
8010                         movLeft2Result(left, MSB32, result, MSB16);
8011                 }
8012                 addSign(result, MSB24, sign);
8013         }
8014         else if(shCount >= 8){
8015                 shCount -= 8;
8016                 if(shCount == 1)
8017                         shiftRLong(left, MSB16, result, sign);
8018                 else if(shCount == 0){
8019                         movLeft2Result(left, MSB16, result, LSB);
8020                         movLeft2Result(left, MSB24, result, MSB16);
8021                         movLeft2Result(left, MSB32, result, MSB24);
8022                         addSign(result, MSB32, sign);
8023                 }
8024                 else{
8025                         shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8026                         shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8027                         /* the last shift is signed */
8028                         shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8029                         addSign(result, MSB32, sign);
8030                 }
8031         }
8032         else{   /* 1 <= shCount <= 7 */
8033                 if(shCount <= 2){
8034                         shiftRLong(left, LSB, result, sign);
8035                         if(shCount == 2)
8036                                 shiftRLong(result, LSB, result, sign);
8037                 }
8038                 else{
8039                         shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8040                         shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8041                         shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8042                 }
8043         }
8044 }
8045
8046 /*-----------------------------------------------------------------*/
8047 /* genRightShiftLiteral - right shifting by known count            */
8048 /*-----------------------------------------------------------------*/
8049 static void genRightShiftLiteral (operand *left,
8050                                                                   operand *right,
8051                                                                   operand *result,
8052                                                                   iCode *ic,
8053                                                                   int sign)
8054 {    
8055         int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8056         int lsize,res_size;
8057         
8058         FENTRY;
8059         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8060         freeAsmop(right,NULL,ic,TRUE);
8061         
8062         aopOp(left,ic,FALSE);
8063         aopOp(result,ic,FALSE);
8064         
8065 #if VIEW_SIZE
8066         pic14_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8067                 AOP_SIZE(left));
8068 #endif
8069         
8070         lsize = pic14_getDataSize(left);
8071         res_size = pic14_getDataSize(result);
8072         /* test the LEFT size !!! */
8073         
8074         /* I suppose that the left size >= result size */
8075         if(shCount == 0){
8076                 while(res_size--)
8077                         movLeft2Result(left, res_size, result, res_size);
8078         }
8079         
8080         else if(shCount >= (lsize * 8)){
8081                 
8082                 if(res_size == 1) {
8083                         emitpcode(POC_CLRF, popGet(AOP(result),LSB));
8084                         if(sign) {
8085                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8086                                 emitpcode(POC_DECF, popGet(AOP(result),LSB));
8087                         }
8088                 } else {
8089                         
8090                         if(sign) {
8091                                 emitpcode(POC_MOVLW, popGetLit(0));
8092                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8093                                 emitpcode(POC_MOVLW, popGetLit(0xff));
8094                                 while(res_size--)
8095                                         emitpcode(POC_MOVWF, popGet(AOP(result),res_size));
8096                                 
8097                         } else {
8098                                 
8099                                 while(res_size--)
8100                                         emitpcode(POC_CLRF, popGet(AOP(result),res_size));
8101                         }
8102                 }
8103         } else {
8104                 
8105                 switch (res_size) {
8106                 case 1:
8107                         genrshOne (result,left,shCount,sign);
8108                         break;
8109                         
8110                 case 2:
8111                         genrshTwo (result,left,shCount,sign);
8112                         break;
8113                         
8114                 case 4:
8115                         genrshFour (result,left,shCount,sign);
8116                         break;
8117                 default :
8118                         break;
8119                 }
8120                 
8121         }
8122
8123         freeAsmop(left,NULL,ic,TRUE);
8124         freeAsmop(result,NULL,ic,TRUE);
8125 }
8126 #endif
8127
8128 #if 0
8129 /*-----------------------------------------------------------------*/
8130 /* genSignedRightShift - right shift of signed number              */
8131 /*-----------------------------------------------------------------*/
8132 static void genSignedRightShift (iCode *ic)
8133 {
8134         operand *right, *left, *result;
8135         int size, offset;
8136         //  char *l;
8137         symbol *tlbl, *tlbl1 ;
8138         pCodeOp *pctemp;
8139         
8140         //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8141         
8142         /* we do it the hard way put the shift count in b
8143         and loop thru preserving the sign */
8144         FENTRY;
8145         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8146         
8147         right = IC_RIGHT(ic);
8148         left  = IC_LEFT(ic);
8149         result = IC_RESULT(ic);
8150         
8151         aopOp(right,ic,FALSE);  
8152         aopOp(left,ic,FALSE);
8153         aopOp(result,ic,FALSE);
8154         
8155         
8156         if ( AOP_TYPE(right) == AOP_LIT) {
8157                 shiftRight_Left2ResultLit (left, result, (int) floatFromVal (AOP(right)->aopu.aop_lit), 1);
8158                 //genRightShiftLiteral (left,right,result,ic,1);
8159                 return ;
8160         }
8161         /* shift count is unknown then we have to form 
8162         a loop get the loop count in B : Note: we take
8163         only the lower order byte since shifting
8164         more that 32 bits make no sense anyway, ( the
8165         largest size of an object can be only 32 bits ) */  
8166         
8167         //pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
8168         //pic14_emitcode("inc","b");
8169         //freeAsmop (right,NULL,ic,TRUE);
8170         //aopOp(left,ic,FALSE);
8171         //aopOp(result,ic,FALSE);
8172         
8173         /* now move the left to the result if they are not the
8174         same */
8175         if (!pic14_sameRegs(AOP(left),AOP(result)) && 
8176                 AOP_SIZE(result) > 1) {
8177                 
8178                 size = AOP_SIZE(result);
8179                 offset=0;
8180                 while (size--) { 
8181                         /*
8182                         l = aopGet(AOP(left),offset,FALSE,TRUE);
8183                         if (*l == '@' && IS_AOP_PREG(result)) {
8184                                 pic14_emitcode("mov","a,%s",l);
8185                                 aopPut(AOP(result),"a",offset);
8186                         } else
8187                         aopPut(AOP(result),l,offset);
8188                         */
8189                         emitpcode(POC_MOVFW,  popGet(AOP(left),offset));
8190                         emitpcode(POC_MOVWF,  popGet(AOP(result),offset));
8191                         
8192                         offset++;
8193                 }
8194         }
8195         
8196         /* mov the highest order bit to OVR */    
8197         tlbl = newiTempLabel(NULL);
8198         tlbl1= newiTempLabel(NULL);
8199         
8200         size = AOP_SIZE(result);
8201         offset = size - 1;
8202         
8203         pctemp = popGetTempReg();  /* grab a temporary working register. */
8204         
8205         emitpcode(POC_MOVFW, popGet(AOP(right),0));
8206         
8207         /* offset should be 0, 1 or 3 */
8208         emitpcode(POC_ANDLW, popGetLit(0x07 + ((offset&3) << 3)));
8209         emitSKPNZ;
8210         emitpcode(POC_GOTO,  popGetLabel(tlbl1->key));
8211         
8212         emitpcode(POC_MOVWF, pctemp);
8213         
8214         
8215         emitpLabel(tlbl->key);
8216         
8217         emitpcode(POC_RLFW,  popGet(AOP(result),offset));
8218         emitpcode(POC_RRF,   popGet(AOP(result),offset));
8219         
8220         while(--size) {
8221                 emitpcode(POC_RRF,   popGet(AOP(result),--offset));
8222         }
8223         
8224         emitpcode(POC_DECFSZ,  pctemp);
8225         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8226         emitpLabel(tlbl1->key);
8227         
8228         popReleaseTempReg(pctemp);
8229 #if 0
8230         size = AOP_SIZE(result);
8231         offset = size - 1;
8232         pic14_emitcode("mov","a,%s",aopGet(AOP(left),offset,FALSE,FALSE));
8233         pic14_emitcode("rlc","a");
8234         pic14_emitcode("mov","ov,c");
8235         /* if it is only one byte then */
8236         if (size == 1) {
8237                 l = aopGet(AOP(left),0,FALSE,FALSE);
8238                 MOVA(l);
8239                 pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8240                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
8241                 pic14_emitcode("mov","c,ov");
8242                 pic14_emitcode("rrc","a");
8243                 pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8244                 pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8245                 aopPut(AOP(result),"a",0);
8246                 goto release ;
8247         }
8248         
8249         reAdjustPreg(AOP(result));
8250         pic14_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8251         pic14_emitcode("","%05d_DS_:",tlbl->key+100);    
8252         pic14_emitcode("mov","c,ov");
8253         while (size--) {
8254                 l = aopGet(AOP(result),offset,FALSE,FALSE);
8255                 MOVA(l);
8256                 pic14_emitcode("rrc","a");         
8257                 aopPut(AOP(result),"a",offset--);
8258         }
8259         reAdjustPreg(AOP(result));
8260         pic14_emitcode("","%05d_DS_:",tlbl1->key+100);
8261         pic14_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8262         
8263 release:
8264 #endif
8265         
8266         freeAsmop(left,NULL,ic,TRUE);
8267         freeAsmop(result,NULL,ic,TRUE);
8268         freeAsmop(right,NULL,ic,TRUE);
8269 }
8270 #endif
8271
8272 /*-----------------------------------------------------------------*/
8273 /* loadSignToC - load the operand's sign bit into CARRY            */
8274 /*-----------------------------------------------------------------*/
8275
8276 static void loadSignToC (operand *op)
8277 {
8278         FENTRY;
8279         assert (op && AOP(op) && AOP_SIZE(op));
8280
8281         emitCLRC;
8282         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(op),AOP_SIZE(op)-1,FALSE,FALSE),7,0));
8283         emitSETC;
8284 }
8285
8286 /*-----------------------------------------------------------------*/
8287 /* genRightShift - generate code for right shifting                */
8288 /*-----------------------------------------------------------------*/
8289 static void genGenericShift (iCode *ic, int shiftRight)
8290 {
8291         operand *right, *left, *result;
8292         sym_link *retype ;
8293         int size;
8294         symbol *tlbl, *tlbl1, *inverselbl;
8295         
8296         FENTRY;
8297         /* if signed then we do it the hard way preserve the
8298         sign bit moving it inwards */
8299         retype = getSpec(operandType(IC_RESULT(ic)));
8300         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8301         
8302         /* signed & unsigned types are treated the same : i.e. the
8303         signed is NOT propagated inwards : quoting from the
8304         ANSI - standard : "for E1 >> E2, is equivalent to division
8305         by 2**E2 if unsigned or if it has a non-negative value,
8306         otherwise the result is implementation defined ", MY definition
8307         is that the sign does not get propagated */
8308         
8309         right = IC_RIGHT(ic);
8310         left  = IC_LEFT(ic);
8311         result = IC_RESULT(ic);
8312         
8313         aopOp(right,ic,FALSE);
8314         aopOp(left,ic,FALSE);
8315         aopOp(result,ic,FALSE);
8316         
8317         /* if the shift count is known then do it 
8318         as efficiently as possible */
8319         if (AOP_TYPE(right) == AOP_LIT) {
8320                 int lit = (int)floatFromVal (AOP(right)->aopu.aop_lit);
8321                 if (lit < 0)
8322                 {
8323                         lit = -lit;
8324                         shiftRight = !shiftRight;
8325                 }
8326                 
8327                 if (shiftRight)
8328                         shiftRight_Left2ResultLit (left, result, lit, !SPEC_USIGN(operandType(left)));
8329                 else
8330                         shiftLeft_Left2ResultLit (left, result, lit);
8331                 //genRightShiftLiteral (left,right,result,ic, 0);
8332                 return ;
8333         }
8334         
8335         /* shift count is unknown then we have to form 
8336         a loop get the loop count in B : Note: we take
8337         only the lower order byte since shifting
8338         more that 32 bits make no sense anyway, ( the
8339         largest size of an object can be only 32 bits ) */  
8340
8341         /* we must not overwrite the shift counter */
8342         assert (!pic14_sameRegs(AOP(right),AOP(result)));
8343         
8344         /* now move the left to the result if they are not the
8345         same */
8346         if (!pic14_sameRegs(AOP(left),AOP(result)))
8347         {
8348                 size = min(AOP_SIZE(result), AOP_SIZE(left));
8349                 while (size--) {
8350                         mov2w(AOP(left), size);
8351                         movwf(AOP(result), size);
8352                 }
8353                 addSign (result, AOP_SIZE(left), !SPEC_USIGN(operandType(left)));
8354         }
8355         
8356         tlbl = newiTempLabel(NULL);
8357         tlbl1= newiTempLabel(NULL);
8358         inverselbl = NULL;
8359         size = AOP_SIZE(result);
8360
8361         mov2w(AOP(right),0);
8362         if (!SPEC_USIGN(operandType(right)))
8363         {
8364                 inverselbl = newiTempLabel(NULL);
8365                 /* signed shift count -- invert shift direction for c<0 */
8366                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
8367                 emitpcode(POC_GOTO, popGetLabel(inverselbl->key));
8368         } // if
8369         emitpcode(POC_SUBLW, popGetLit(0));     /* -count in WREG, 0-x > 0 --> BORROW = !CARRY --> CARRY is clear! */
8370         /* check for `a = b >> c' with `-c == 0' */
8371         emitSKPNZ;
8372         emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8373         emitpLabel(tlbl->key);
8374         /* propagate the sign bit inwards for SIGNED result */
8375         if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8376         genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8377         emitpcode(POC_ADDLW,  popGetLit(1));    /* clears CARRY (unless W==0 afterwards) */
8378         emitSKPC;
8379         emitpcode(POC_GOTO,popGetLabel(tlbl->key));
8380
8381         if (!SPEC_USIGN(operandType(right)))
8382         {
8383                 symbol *inv_loop = newiTempLabel(NULL);
8384
8385                 shiftRight = !shiftRight;       /* invert shift direction */
8386                 
8387                 /* we came here from the code above -- we are done */
8388                 emitpcode(POC_GOTO, popGetLabel(tlbl1->key));
8389                 
8390                 /* emit code for shifting N<0 steps, count is already in W */
8391                 emitpLabel(inverselbl->key);
8392                 if (!shiftRight || SPEC_USIGN(operandType(result))) emitCLRC;
8393                 emitpLabel(inv_loop->key);
8394                 /* propagate the sign bit inwards for SIGNED result */
8395                 if (shiftRight && !SPEC_USIGN(operandType(result))) loadSignToC(result);
8396                 genMultiAsm(shiftRight ? POC_RRF : POC_RLF, result, size, shiftRight);
8397                 emitpcode(POC_ADDLW, popGetLit(1));
8398                 emitSKPC;
8399                 emitpcode(POC_GOTO, popGetLabel(inv_loop->key));
8400         } // if
8401         
8402         emitpLabel(tlbl1->key);
8403         
8404         freeAsmop(left,NULL,ic,TRUE);
8405         freeAsmop (right,NULL,ic,TRUE);
8406         freeAsmop(result,NULL,ic,TRUE);
8407 }
8408
8409 static void genRightShift (iCode *ic)
8410 {
8411         genGenericShift(ic, 1);
8412 }
8413
8414 static void genLeftShift (iCode *ic)
8415 {
8416         genGenericShift(ic, 0);
8417 }
8418
8419 /*-----------------------------------------------------------------*/
8420 /* SetIrp - Set IRP bit                                            */
8421 /*-----------------------------------------------------------------*/
8422 void SetIrp(operand *result) {
8423         FENTRY;
8424         if (AOP_TYPE(result) == AOP_LIT) {
8425                 unsigned lit = (unsigned)operandLitValue(result);
8426                 if (lit&0x100)
8427                         emitSETIRP;
8428                 else
8429                         emitCLRIRP;
8430         } else {
8431                 if (PCOP(AOP(result))->type == PO_LITERAL) {
8432                         int addrs = PCOL(AOP(result))->lit;
8433                         if (addrs & 0x100)
8434                                 emitSETIRP;
8435                         else
8436                                 emitCLRIRP;
8437                 } else {
8438                         emitCLRIRP; /* always ensure this is clear as it may have previouly been set */
8439                         if(AOP_SIZE(result) > 1) {
8440                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),1,FALSE,FALSE),0,0));
8441                                 emitSETIRP;
8442                         }
8443                 }
8444         }
8445 }
8446
8447 static void
8448 setup_fsr (operand *ptr)
8449 {
8450   mov2w_op(ptr, 0);
8451   emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8452
8453   /* also setup-up IRP */
8454   SetIrp (ptr);
8455 }
8456
8457 /*-----------------------------------------------------------------*/
8458 /* emitPtrByteGet - emits code to get a byte into WREG from an     */
8459 /*                  arbitrary pointer (__code, __data, generic)    */
8460 /*-----------------------------------------------------------------*/
8461 static void
8462 emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
8463 {
8464     FENTRY;
8465     switch (p_type)
8466     {
8467     case POINTER:
8468     case FPOINTER:
8469       if (!alreadyAddressed) setup_fsr (src);
8470       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
8471       break;
8472     
8473     case CPOINTER:
8474       assert( AOP_SIZE(src) == 2 );
8475       mov2w_op(src, 0);
8476       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8477       mov2w_op(src, 1);
8478       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8479       emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE));   /* GPOINTER tag for __code space */
8480       call_libraryfunc ("__gptrget1");
8481       break;
8482     
8483     case GPOINTER:
8484       assert( AOP_SIZE(src) == 3 );
8485       mov2w_op(src, 0);
8486       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8487       mov2w_op(src, 1);
8488       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8489       mov2w_op(src, 2);
8490       call_libraryfunc ("__gptrget1");
8491       break;
8492     
8493     default:
8494       assert( !"unhandled pointer type" );
8495       break;
8496     }
8497 }
8498
8499 /*-----------------------------------------------------------------*/
8500 /* emitPtrByteSet - emits code to set a byte from src through a    */
8501 /* pointer register INDF (legacy 8051 uses R0, R1, or DPTR).       */
8502 /*-----------------------------------------------------------------*/
8503 static void
8504 emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
8505 {
8506     FENTRY;
8507     switch (p_type)
8508     {
8509     case POINTER:
8510     case FPOINTER:
8511       if (!alreadyAddressed) setup_fsr (dst);
8512       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
8513       break;
8514     
8515     case CPOINTER:
8516       assert( !"trying to assign to __code pointer" );
8517       break;
8518     
8519     case GPOINTER:
8520       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-2));
8521       mov2w_op(dst, 0);
8522       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
8523       mov2w_op(dst, 1);
8524       emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
8525       mov2w_op(dst, 2);
8526       call_libraryfunc ("__gptrput1");
8527       break;
8528
8529     default:
8530       assert( !"unhandled pointer type" );
8531       break;
8532     }
8533 }
8534
8535 /*-----------------------------------------------------------------*/
8536 /* genUnpackBits - generates code for unpacking bits               */
8537 /*-----------------------------------------------------------------*/
8538 static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx)
8539 {    
8540   int rsize;            /* result size */
8541   sym_link *etype;      /* bitfield type information */
8542   int blen;             /* bitfield length */
8543   int bstr;             /* bitfield starting bit within byte */
8544
8545   FENTRY;
8546   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8547   etype = getSpec(operandType(result));
8548   rsize = getSize (operandType (result));
8549   blen = SPEC_BLEN (etype);
8550   bstr = SPEC_BSTR (etype);
8551
8552   /* single bit field case */
8553   if (blen == 1) {
8554     if (ifx) { /* that is for an if statement */
8555       pCodeOp *pcop;
8556       resolvedIfx rIfx;
8557       resolveIfx(&rIfx,ifx);
8558       if (ptype == -1) /* direct */
8559         pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
8560       else
8561         pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
8562       emitpcode((rIfx.condition) ? POC_BTFSC : POC_BTFSS,pcop);
8563       emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
8564       ifx->generated=1;
8565     } else {
8566       int i;
8567       assert (!pic14_sameRegs (AOP(result), AOP(left)));
8568       for (i=0; i < AOP_SIZE(result); i++)
8569         emitpcode (POC_CLRF, popGet (AOP(result), i));
8570
8571       switch (ptype)
8572       {
8573       case -1:
8574         emitpcode(POC_BTFSC,newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0));
8575         /* adjust result below */
8576         break;
8577         
8578       case POINTER:
8579       case FPOINTER:
8580       case GPOINTER:
8581       case CPOINTER:
8582         emitPtrByteGet (left, ptype, FALSE);
8583         emitpcode(POC_ANDLW, popGetLit (1UL << bstr));
8584         emitSKPZ;
8585         /* adjust result below */
8586         break;
8587         
8588       default:
8589         assert( !"unhandled pointer type" );
8590       } // switch
8591
8592       /* move sign-/zero extended bit to result */
8593       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
8594         emitpcode (POC_INCF, popGet (AOP(result), 0));
8595       } else {
8596         emitpcode (POC_DECF, popGet (AOP(result), 0));
8597       }
8598       addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8599     }
8600     return;
8601   }
8602   else if (blen <= 8 && ((blen + bstr) <= 8))
8603   {
8604     /* blen > 1 */
8605     int i;
8606
8607     for (i=0; i < AOP_SIZE(result); i++)
8608       emitpcode (POC_CLRF, popGet (AOP(result), i));
8609
8610     switch (ptype)
8611     {
8612     case -1:
8613       mov2w(AOP(left), 0);
8614       break;
8615       
8616     case POINTER:
8617     case FPOINTER:
8618     case GPOINTER:
8619     case CPOINTER:
8620       emitPtrByteGet (left, ptype, FALSE);
8621       break;
8622       
8623     default:
8624       assert( !"unhandled pointer type" );
8625     } // switch
8626
8627     if (blen < 8)
8628       emitpcode(POC_ANDLW, popGetLit ((((1UL << blen)-1) << bstr) & 0x00ff));
8629     movwf(AOP(result), 0);
8630     AccRsh (popGet(AOP(result), 0), bstr, 1); /* zero extend the bitfield */
8631
8632     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen != 8))
8633     {
8634       /* signed bitfield */
8635       assert (bstr + blen > 0);
8636       emitpcode(POC_MOVLW, popGetLit (0x00ff << (bstr + blen)));
8637       emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE), bstr + blen - 1, 0));
8638       emitpcode(POC_IORWF, popGet(AOP(result),0));
8639     }
8640     addSign (result, 1, !SPEC_USIGN(OP_SYM_ETYPE(left)));
8641     return;
8642   }
8643
8644   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
8645 }
8646
8647 #if 1
8648 /*-----------------------------------------------------------------*/
8649 /* genDataPointerGet - generates code when ptr offset is known     */
8650 /*-----------------------------------------------------------------*/
8651 static void genDataPointerGet (operand *left, 
8652         operand *result, 
8653         iCode *ic)
8654 {
8655         int size , offset = 0;
8656                 
8657         FENTRY;
8658         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8659         
8660         
8661         /* optimization - most of the time, left and result are the same
8662         * address, but different types. for the pic code, we could omit
8663         * the following
8664         */
8665         aopOp(result,ic,TRUE);
8666         
8667         if (pic14_sameRegs (AOP(left), AOP(result)))
8668                 return;
8669         
8670         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8671         
8672         //emitpcode(POC_MOVFW, popGet(AOP(left),0));
8673         
8674         size = AOP_SIZE(result);
8675         if (size > getSize(OP_SYM_ETYPE(left))) size = getSize(OP_SYM_ETYPE(left));
8676         
8677         offset = 0;
8678         while (size--) {
8679                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
8680                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
8681                 offset++;
8682         }
8683         
8684         freeAsmop(left,NULL,ic,TRUE);
8685         freeAsmop(result,NULL,ic,TRUE);
8686 }
8687 #endif
8688
8689 /*-----------------------------------------------------------------*/
8690 /* genNearPointerGet - pic14_emitcode for near pointer fetch       */
8691 /*-----------------------------------------------------------------*/
8692 static void genNearPointerGet (operand *left, 
8693                                                            operand *result, 
8694                                                            iCode *ic)
8695 {
8696         asmop *aop = NULL;
8697         sym_link *ltype = operandType(left);
8698         sym_link *rtype = operandType(result);
8699         sym_link *retype= getSpec(rtype);      /* bitfield type information */
8700         int direct = 0;
8701
8702         FENTRY;
8703         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8704         
8705         
8706         aopOp(left,ic,FALSE);
8707         
8708         /* if left is rematerialisable and
8709         result is not bit variable type and
8710         the left is pointer to data space i.e
8711         lower 128 bytes of space */
8712         if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8713                 !IS_BITVAR(retype)         &&
8714                 PIC_IS_DATA_PTR(ltype)) {
8715                 genDataPointerGet (left,result,ic);
8716                 return ;
8717         }
8718         
8719         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8720         aopOp (result,ic,FALSE);
8721         
8722         /* Check if can access directly instead of via a pointer */
8723         if ((PCOP(AOP(left))->type == PO_LITERAL || PCOP(AOP(left))->type == PO_IMMEDIATE)
8724                 && AOP_SIZE(result) == 1)
8725         {
8726                 direct = 1;
8727         }
8728
8729         if (IS_BITFIELD(getSpec(operandType(result)))) 
8730         {
8731                 genUnpackBits (result,left,direct?-1:POINTER,ifxForOp(IC_RESULT(ic),ic));
8732                 goto release;
8733         }
8734         
8735         /* If the pointer value is not in a the FSR then need to put it in */
8736         /* Must set/reset IRP bit for use with FSR. */
8737         if (!direct)
8738           setup_fsr (left);
8739         
8740 //      sym_link *etype;
8741         /* if bitfield then unpack the bits */
8742         {
8743                 /* we have can just get the values */
8744                 int size = AOP_SIZE(result);
8745                 int offset = 0 ;  
8746                 
8747                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8748                 
8749                 while(size--) {
8750                         if (direct)
8751                                 emitpcode(POC_MOVWF,popGet(AOP(left),0));
8752                         else
8753                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
8754                         if (AOP_TYPE(result) == AOP_LIT) {
8755                                 emitpcode(POC_MOVLW,popGet(AOP(result),offset));
8756                         } else {
8757                                 emitpcode(POC_MOVWF,popGet(AOP(result),offset));
8758                         }
8759                         if (size && !direct)
8760                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
8761                         offset++;
8762                 }
8763         }
8764         
8765         /* now some housekeeping stuff */
8766         if (aop) {
8767                 /* we had to allocate for this iCode */
8768                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8769                 freeAsmop(NULL,aop,ic,TRUE);
8770         } else { 
8771                 /* we did not allocate which means left
8772                 already in a pointer register, then
8773                 if size > 0 && this could be used again
8774                 we have to point it back to where it 
8775                 belongs */
8776                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8777                 if (AOP_SIZE(result) > 1 &&
8778                         !OP_SYMBOL(left)->remat &&
8779                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8780                         ic->depth )) {
8781                         int size = AOP_SIZE(result) - 1;
8782                         while (size--)
8783                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
8784                 }
8785         }
8786         
8787 release:
8788         /* done */
8789         freeAsmop(left,NULL,ic,TRUE);
8790         freeAsmop(result,NULL,ic,TRUE);
8791
8792 }
8793
8794 #if 0
8795 /*-----------------------------------------------------------------*/
8796 /* genPagedPointerGet - pic14_emitcode for paged pointer fetch           */
8797 /*-----------------------------------------------------------------*/
8798 static void genPagedPointerGet (operand *left, 
8799                                                                 operand *result, 
8800                                                                 iCode *ic)
8801 {
8802         asmop *aop = NULL;
8803         regs *preg = NULL ;
8804         char *rname ;
8805         sym_link *rtype, *retype;    
8806         
8807         FENTRY;
8808         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8809         
8810         rtype = operandType(result);
8811         retype= getSpec(rtype);
8812         
8813         aopOp(left,ic,FALSE);
8814         
8815         /* if the value is already in a pointer register
8816         then don't need anything more */
8817         if (!AOP_INPREG(AOP(left))) {
8818                 /* otherwise get a free pointer register */
8819                 aop = newAsmop(0);
8820                 preg = getFreePtr(ic,&aop,FALSE);
8821                 pic14_emitcode("mov","%s,%s",
8822                         preg->name,
8823                         aopGet(AOP(left),0,FALSE,TRUE));
8824                 rname = preg->name ;
8825         } else
8826                 rname = aopGet(AOP(left),0,FALSE,FALSE);
8827         
8828         freeAsmop(left,NULL,ic,TRUE);
8829         aopOp (result,ic,FALSE);
8830         
8831         /* if bitfield then unpack the bits */
8832         if (IS_BITFIELD(retype)) 
8833                 genUnpackBits (result,left,rname,PPOINTER,0);
8834         else {
8835                 /* we have can just get the values */
8836                 int size = AOP_SIZE(result);
8837                 int offset = 0 ;  
8838                 
8839                 while (size--) {
8840                         
8841                         pic14_emitcode("movx","a,@%s",rname);
8842                         aopPut(AOP(result),"a",offset);
8843                         
8844                         offset++ ;
8845                         
8846                         if (size)
8847                                 pic14_emitcode("inc","%s",rname);
8848                 }
8849         }
8850         
8851         /* now some housekeeping stuff */
8852         if (aop) {
8853                 /* we had to allocate for this iCode */
8854                 freeAsmop(NULL,aop,ic,TRUE);
8855         } else { 
8856         /* we did not allocate which means left
8857         already in a pointer register, then
8858         if size > 0 && this could be used again
8859         we have to point it back to where it 
8860                 belongs */
8861                 if (AOP_SIZE(result) > 1 &&
8862                         !OP_SYMBOL(left)->remat &&
8863                         ( OP_SYMBOL(left)->liveTo > ic->seq ||
8864                         ic->depth )) {
8865                         int size = AOP_SIZE(result) - 1;
8866                         while (size--)
8867                                 pic14_emitcode("dec","%s",rname);
8868                 }
8869         }
8870         
8871         /* done */
8872         freeAsmop(result,NULL,ic,TRUE);
8873         
8874         
8875 }
8876
8877 /*-----------------------------------------------------------------*/
8878 /* genFarPointerGet - gget value from far space                    */
8879 /*-----------------------------------------------------------------*/
8880 static void genFarPointerGet (operand *left,
8881                                                           operand *result, iCode *ic)
8882 {
8883         int size, offset ;
8884         sym_link *retype = getSpec(operandType(result));
8885         
8886         FENTRY;
8887         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8888         
8889         aopOp(left,ic,FALSE);
8890         
8891         /* if the operand is already in dptr 
8892         then we do nothing else we move the value to dptr */
8893         if (AOP_TYPE(left) != AOP_STR) {
8894                 /* if this is remateriazable */
8895                 if (AOP_TYPE(left) == AOP_IMMD)
8896                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8897                 else { /* we need to get it byte by byte */
8898                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8899                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8900                         if (options.model == MODEL_FLAT24)
8901                         {
8902                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8903                         }
8904                 }
8905         }
8906         /* so dptr know contains the address */
8907         freeAsmop(left,NULL,ic,TRUE);
8908         aopOp(result,ic,FALSE);
8909         
8910         /* if bit then unpack */
8911         if (IS_BITFIELD(retype)) 
8912                 genUnpackBits(result,left,"dptr",FPOINTER,0);
8913         else {
8914                 size = AOP_SIZE(result);
8915                 offset = 0 ;
8916                 
8917                 while (size--) {
8918                         pic14_emitcode("movx","a,@dptr");
8919                         aopPut(AOP(result),"a",offset++);
8920                         if (size)
8921                                 pic14_emitcode("inc","dptr");
8922                 }
8923         }
8924         
8925         freeAsmop(result,NULL,ic,TRUE);
8926 }
8927 #endif
8928
8929 #if 0
8930 /*-----------------------------------------------------------------*/
8931 /* genCodePointerGet - get value from code space                  */
8932 /*-----------------------------------------------------------------*/
8933 static void genCodePointerGet (operand *left,
8934                                                            operand *result, iCode *ic)
8935 {
8936         int size, offset ;
8937         sym_link *retype = getSpec(operandType(result));
8938         
8939         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8940         
8941         aopOp(left,ic,FALSE);
8942         
8943         /* if the operand is already in dptr 
8944         then we do nothing else we move the value to dptr */
8945         if (AOP_TYPE(left) != AOP_STR) {
8946                 /* if this is remateriazable */
8947                 if (AOP_TYPE(left) == AOP_IMMD)
8948                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(left),0,TRUE,FALSE));
8949                 else { /* we need to get it byte by byte */
8950                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(left),0,FALSE,FALSE));
8951                         pic14_emitcode("mov","dph,%s",aopGet(AOP(left),1,FALSE,FALSE));
8952                         if (options.model == MODEL_FLAT24)
8953                         {
8954                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(left),2,FALSE,FALSE));
8955                         }
8956                 }
8957         }
8958         /* so dptr know contains the address */
8959         freeAsmop(left,NULL,ic,TRUE);
8960         aopOp(result,ic,FALSE);
8961         
8962         /* if bit then unpack */
8963         if (IS_BITFIELD(retype)) 
8964                 genUnpackBits(result,left,"dptr",CPOINTER,0);
8965         else {
8966                 size = AOP_SIZE(result);
8967                 offset = 0 ;
8968                 
8969                 while (size--) {
8970                         pic14_emitcode("clr","a");
8971                         pic14_emitcode("movc","a,@a+dptr");
8972                         aopPut(AOP(result),"a",offset++);
8973                         if (size)
8974                                 pic14_emitcode("inc","dptr");
8975                 }
8976         }
8977         
8978         freeAsmop(result,NULL,ic,TRUE);
8979 }
8980 #endif
8981 /*-----------------------------------------------------------------*/
8982 /* genGenPointerGet - gget value from generic pointer space        */
8983 /*-----------------------------------------------------------------*/
8984 static void genGenPointerGet (operand *left,
8985                                                           operand *result, iCode *ic)
8986 {
8987         FENTRY;
8988         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8989         aopOp(left,ic,FALSE);
8990         aopOp(result,ic,FALSE);
8991         
8992         
8993         DEBUGpic14_AopType(__LINE__,left,NULL,result);
8994
8995         if (IS_BITFIELD(getSpec(operandType(result))))
8996         {
8997           genUnpackBits (result, left, GPOINTER, ifxForOp (IC_RESULT(ic), ic));
8998           return;
8999         }
9000
9001         {
9002           /* emit call to __gptrget */
9003           char *func[] = {NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4"};
9004           int size = AOP_SIZE(result);
9005           int idx = 0;
9006
9007           assert (size > 0 && size <= 4);
9008
9009           /* pass arguments */
9010           assert (AOP_SIZE(left) == 3);
9011           mov2w(AOP(left), 0);
9012           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9013           mov2w(AOP(left), 1);
9014           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9015           mov2w(AOP(left), 2);
9016           call_libraryfunc (func[size]);
9017           
9018           /* save result */
9019           movwf (AOP(result), --size);
9020           while (size--) {
9021             emitpcode (POC_MOVFW,popRegFromIdx (Gstack_base_addr - idx++));
9022             movwf (AOP(result), size);
9023           } // while
9024         }
9025         
9026         freeAsmop(left,NULL,ic,TRUE);
9027         freeAsmop(result,NULL,ic,TRUE);
9028         
9029 }
9030
9031 /*-----------------------------------------------------------------*/
9032 /* genConstPointerGet - get value from const generic pointer space */
9033 /*-----------------------------------------------------------------*/
9034 static void genConstPointerGet (operand *left,
9035                                                                 operand *result, iCode *ic)
9036 {
9037         //sym_link *retype = getSpec(operandType(result));
9038         #if 0
9039         symbol *albl, *blbl;//, *clbl;
9040         pCodeOp *pcop;
9041         #endif
9042         PIC_OPCODE poc;
9043         int i, size, lit;
9044         
9045         FENTRY;
9046         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9047         aopOp(left,ic,FALSE);
9048         aopOp(result,ic,FALSE);
9049         
9050         size = AOP_SIZE(result);
9051         
9052         DEBUGpic14_AopType(__LINE__,left,NULL,result);
9053         
9054         DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__);
9055
9056         lit = op_isLitLike (left);
9057         poc = lit ? POC_MOVLW : POC_MOVFW;
9058
9059         if (IS_BITFIELD(getSpec(operandType(result))))
9060         {
9061                 genUnpackBits (result, left, lit ? -1 : CPOINTER, ifxForOp (IC_RESULT(ic), ic));
9062                 goto release;
9063         }
9064
9065         {
9066                 char *func[] = { NULL, "__gptrget1", "__gptrget2", "__gptrget3", "__gptrget4" };
9067                 int size = min(getSize(OP_SYM_ETYPE(left)), AOP_SIZE(result));
9068                 assert (size > 0 && size <= 4);
9069                 
9070                 mov2w_op(left, 0);
9071                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr-1));
9072                 mov2w_op(left, 1);
9073                 emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9074                 emitpcode(POC_MOVLW, popGetLit (GPTRTAG_CODE)); /* GPOINTER tag for __code space */
9075                 call_libraryfunc (func[size]);
9076
9077                 movwf(AOP(result),size-1);
9078                 for (i = 1; i < size; i++)
9079                 {
9080                         emitpcode(POC_MOVFW, popRegFromIdx (Gstack_base_addr+1-i));
9081                         movwf(AOP(result),size - 1 - i);
9082                 } // for
9083         }
9084         
9085 release:
9086         freeAsmop(left,NULL,ic,TRUE);
9087         freeAsmop(result,NULL,ic,TRUE);
9088         
9089 }
9090 /*-----------------------------------------------------------------*/
9091 /* genPointerGet - generate code for pointer get                   */
9092 /*-----------------------------------------------------------------*/
9093 static void genPointerGet (iCode *ic)
9094 {
9095         operand *left, *result ;
9096         sym_link *type, *etype;
9097         int p_type = -1;
9098         
9099         FENTRY;
9100         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9101         
9102         left = IC_LEFT(ic);
9103         result = IC_RESULT(ic) ;
9104         
9105         /* depending on the type of pointer we need to
9106         move it to the correct pointer register */
9107         type = operandType(left);
9108         etype = getSpec(type);
9109         
9110         if (IS_PTR_CONST(type))
9111                 DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
9112         
9113         /* if left is of type of pointer then it is simple */
9114         if (IS_PTR(type) && !IS_FUNC(type->next)) 
9115                 p_type = DCL_TYPE(type);
9116         else {
9117                 /* we have to go by the storage class */
9118                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9119                 
9120                 DEBUGpic14_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9121                 
9122                 if (SPEC_OCLS(etype)->codesp ) {
9123                         DEBUGpic14_emitcode ("; ***","%d - cpointer",__LINE__);
9124                         //p_type = CPOINTER ; 
9125                 }
9126                 else
9127                         if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9128                                 DEBUGpic14_emitcode ("; ***","%d - fpointer",__LINE__);
9129                         /*p_type = FPOINTER ;*/ 
9130                         else
9131                                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9132                                         DEBUGpic14_emitcode ("; ***","%d - ppointer",__LINE__);
9133                                 /*        p_type = PPOINTER; */
9134                                 else
9135                                         if (SPEC_OCLS(etype) == idata )
9136                                                 DEBUGpic14_emitcode ("; ***","%d - ipointer",__LINE__);
9137                                         /*      p_type = IPOINTER; */
9138                                         else
9139                                                 DEBUGpic14_emitcode ("; ***","%d - pointer",__LINE__);
9140                                         /*      p_type = POINTER ; */
9141         }
9142         
9143         /* now that we have the pointer type we assign
9144         the pointer values */
9145         switch (p_type) {
9146                 
9147         case POINTER: 
9148         case FPOINTER:
9149         //case IPOINTER:
9150                 genNearPointerGet (left,result,ic);
9151                 break;
9152 /*
9153         case PPOINTER:
9154                 genPagedPointerGet(left,result,ic);
9155                 break;
9156                 
9157         case FPOINTER:
9158                 genFarPointerGet (left,result,ic);
9159                 break;
9160 */              
9161         case CPOINTER:
9162                 genConstPointerGet (left,result,ic);
9163                 break;
9164                 
9165         case GPOINTER:
9166                 genGenPointerGet (left,result,ic);
9167                 break;
9168         default:
9169                 assert ( !"unhandled pointer type" );
9170                 break;
9171         }
9172         
9173 }
9174
9175 /*-----------------------------------------------------------------*/
9176 /* genPackBits - generates code for packed bit storage             */
9177 /*-----------------------------------------------------------------*/
9178 static void genPackBits(sym_link *etype,operand *result,operand *right,int p_type)
9179 {
9180   int blen;             /* bitfield length */
9181   int bstr;             /* bitfield starting bit within byte */
9182   int litval;           /* source literal value (if AOP_LIT) */
9183   unsigned char mask;   /* bitmask within current byte */
9184
9185   FENTRY;
9186   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9187
9188   blen = SPEC_BLEN (etype);
9189   bstr = SPEC_BSTR (etype);
9190
9191   /* If the bitfield length is less than a byte and does not cross byte boundaries */
9192   if ((blen <= 8) && ((bstr + blen) <= 8))
9193   {
9194     mask = ((unsigned char) (0xFF << (blen + bstr)) |
9195             (unsigned char) (0xFF >> (8 - bstr)));
9196
9197     if (AOP_TYPE (right) == AOP_LIT)
9198     {
9199       /* Case with a bitfield length <8 and literal source */
9200       int lit = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9201       if (blen == 1) {
9202         pCodeOp *pcop;
9203         
9204         switch (p_type)
9205         {
9206         case -1:
9207           if (AOP(result)->type == AOP_PCODE)
9208             pcop = newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0);
9209           else
9210             pcop = popGet(AOP(result),0);
9211           emitpcode(lit?POC_BSF:POC_BCF,pcop);
9212           break;
9213         
9214         case POINTER:
9215         case FPOINTER:
9216           setup_fsr (result);
9217           emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
9218           break;
9219         
9220         case CPOINTER:
9221           assert( !"trying to assign to bitfield via pointer to __code space" );
9222           break;
9223         
9224         case GPOINTER:
9225           emitPtrByteGet(result, p_type, FALSE);
9226           if (lit) {
9227             emitpcode(POC_IORLW, newpCodeOpLit (1UL << bstr));
9228           } else {
9229             emitpcode(POC_ANDLW, newpCodeOpLit ((~(1UL << bstr)) & 0x0ff));
9230           }
9231           emitPtrByteSet(result, p_type, TRUE);
9232           break;
9233         
9234         default:
9235           assert( !"unhandled pointer type" );
9236           break;
9237         } // switch (p_type)
9238       } else {
9239         /* blen > 1 */
9240         litval = lit << bstr;
9241         litval &= (~mask) & 0x00ff;
9242         
9243         switch (p_type)
9244         {
9245         case -1:
9246           mov2w (AOP(result), 0);
9247           if ((litval|mask) != 0x00ff)
9248             emitpcode(POC_ANDLW, popGetLit (mask));
9249           if (litval != 0x00)
9250             emitpcode(POC_IORLW, popGetLit (litval));
9251           movwf (AOP(result), 0);
9252           break;
9253         
9254         case POINTER:
9255         case FPOINTER:
9256         case GPOINTER:
9257           emitPtrByteGet(result, p_type, FALSE);
9258           if ((litval|mask) != 0x00ff)
9259             emitpcode(POC_ANDLW, popGetLit (mask));
9260           if (litval != 0x00)
9261             emitpcode(POC_IORLW, popGetLit (litval));
9262           emitPtrByteSet(result, p_type, TRUE);
9263           break;
9264         
9265         case CPOINTER:
9266           assert( !"trying to assign to bitfield via pointer to __code space" );
9267           break;
9268         
9269         default:
9270           assert( !"unhandled pointer type" );
9271           break;
9272         } // switch
9273       } // if (blen > 1)
9274     }
9275     else
9276     {
9277       /* right is no literal */
9278       if (blen==1) {
9279         switch (p_type)
9280         {
9281         case -1:
9282           /* Note more efficient code, of pre clearing bit then only setting it if required,
9283            * can only be done if it is known that the result is not a SFR */
9284           emitpcode(POC_RRFW,popGet(AOP(right),0));
9285           emitSKPC;
9286           emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9287           emitSKPNC;
9288           emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
9289           break;
9290         
9291         case POINTER:
9292         case FPOINTER:
9293         case GPOINTER:
9294           emitPtrByteGet (result, p_type, FALSE);
9295           emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9296           emitpcode(POC_ANDLW, newpCodeOpLit (~(1UL << bstr) & 0x0ff));
9297           emitpcode(POC_BTFSC, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
9298           emitpcode(POC_IORLW, newpCodeOpLit ((1UL << bstr) & 0x0ff));
9299           emitPtrByteSet (result, p_type, TRUE);
9300           break;
9301         
9302         case CPOINTER:
9303           assert( !"trying to assign to bitfield via pointer to __code space" );
9304           break;
9305         
9306         default:
9307           assert( !"unhandled pointer type" );
9308           break;
9309         } // switch
9310         return;
9311       } else {
9312         /* Case with a bitfield 1 < length <= 8 and arbitrary source */
9313         pCodeOp *temp = popGetTempReg ();
9314
9315         mov2w (AOP(right), 0);
9316         if (blen < 8) {
9317           emitpcode (POC_ANDLW, popGetLit ((1UL << blen)-1));
9318         }
9319         emitpcode(POC_MOVWF, temp);
9320         if (bstr) {
9321           AccLsh (temp, bstr);
9322         }
9323         
9324         switch (p_type)
9325         {
9326         case -1:
9327           mov2w (AOP(result), 0);
9328           emitpcode(POC_ANDLW, popGetLit (mask));
9329           emitpcode(POC_IORFW, temp);
9330           movwf (AOP(result), 0);
9331           break;
9332         
9333         case POINTER:
9334         case FPOINTER:
9335         case GPOINTER:
9336           emitPtrByteGet (result, p_type, FALSE);
9337           emitpcode(POC_ANDLW, popGetLit (mask));
9338           emitpcode(POC_IORFW, temp);
9339           emitPtrByteSet (result, p_type, TRUE);
9340           break;
9341         
9342         case CPOINTER:
9343           assert( !"trying to assign to bitfield via pointer to __code space" );
9344           break;
9345         
9346         default:
9347           assert( !"unhandled pointer type" );
9348           break;
9349         } // switch
9350
9351         popReleaseTempReg (temp);
9352       } // if (blen > 1)
9353     } // if (AOP(right)->type != AOP_LIT)
9354     return;
9355   } // if (blen <= 8 && ((blen + bstr) <= 8))
9356
9357   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
9358 }
9359
9360 unsigned long
9361 bitpatternFromVal (value *val)
9362 {
9363   union {
9364     float d;
9365     uint32_t l;
9366   } float_long;
9367
9368   assert (sizeof (float) == sizeof (uint32_t));
9369
9370   //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
9371
9372   switch (SPEC_NOUN(val->type))
9373   {
9374   case V_INT:
9375   case V_CHAR:
9376     return (unsigned long)floatFromVal (val);
9377     
9378   case V_FLOAT:
9379   case V_DOUBLE:
9380     float_long.d = floatFromVal (val);
9381     return float_long.l;
9382     
9383   default:
9384     assert( !"unhandled value type" );
9385     break;
9386   }
9387
9388   float_long.d = floatFromVal (val);
9389   return float_long.l;
9390 }
9391
9392 /*-----------------------------------------------------------------*/
9393 /* genDataPointerSet - remat pointer to data space                 */
9394 /*-----------------------------------------------------------------*/
9395 static void genDataPointerSet(operand *right,
9396         operand *result,
9397         iCode *ic)
9398 {
9399         int size, offset = 0 ;
9400         int ressize;
9401         
9402         FENTRY;
9403         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9404         aopOp(right,ic,FALSE);
9405         aopOp(result,ic,FALSE);
9406         
9407         assert (IS_SYMOP(result));
9408         assert (IS_PTR(OP_SYM_TYPE(result)));
9409         
9410         size = AOP_SIZE(right);
9411         ressize = getSize(OP_SYM_ETYPE(result));
9412         if (size > ressize) size = ressize;
9413         //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
9414         
9415         //assert( !"what's going on here?" );
9416
9417         /*
9418         if ( AOP_TYPE(result) == AOP_PCODE) {
9419         fprintf(stderr,"genDataPointerSet   %s, %d\n",
9420         AOP(result)->aopu.pcop->name,
9421         PCOI(AOP(result)->aopu.pcop)->offset);
9422         }
9423         */
9424         
9425         // tsd, was l+1 - the underline `_' prefix was being stripped
9426         while (size--) {
9427                 emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
9428                 
9429                 if (AOP_TYPE(right) == AOP_LIT) {
9430                         /* XXX: might be float... */
9431                         unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9432                         lit = lit >> (8*offset);
9433                         //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
9434                         if(lit&0xff) {
9435                                 emitpcode(POC_MOVLW, popGetLit(lit&0xff));
9436                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9437                         } else {
9438                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
9439                         }
9440                 } else {
9441                         //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
9442                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
9443                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9444                 }
9445                 
9446                 offset++;
9447         }
9448         
9449         freeAsmop(right,NULL,ic,TRUE);
9450         freeAsmop(result,NULL,ic,TRUE);
9451 }
9452
9453 /*-----------------------------------------------------------------*/
9454 /* genNearPointerSet - pic14_emitcode for near pointer put         */
9455 /*-----------------------------------------------------------------*/
9456 static void genNearPointerSet (operand *right,
9457                                                            operand *result, 
9458                                                            iCode *ic)
9459 {
9460         asmop *aop = NULL;
9461         sym_link *ptype = operandType(result);
9462         sym_link *retype = getSpec(operandType(right));
9463         sym_link *letype = getSpec(ptype);
9464         int direct = 0;
9465         
9466         
9467         FENTRY;
9468         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9469         aopOp(result,ic,FALSE);
9470         
9471 #if 1
9472         /* if the result is rematerializable &
9473         in data space & not a bit variable */
9474         //if (AOP_TYPE(result) == AOP_IMMD &&
9475         if (AOP_TYPE(result) == AOP_PCODE &&
9476                 PIC_IS_DATA_PTR(ptype) &&
9477                 !IS_BITVAR (retype) &&
9478                 !IS_BITVAR (letype)) {
9479                 genDataPointerSet (right,result,ic);
9480                 freeAsmop(result,NULL,ic,TRUE);
9481                 return;
9482         }
9483 #endif
9484
9485         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9486         aopOp(right,ic,FALSE);
9487         DEBUGpic14_AopType(__LINE__,NULL,right,result);
9488         
9489         /* Check if can access directly instead of via a pointer */
9490         if (PCOP(AOP(result))->type == PO_LITERAL && AOP_SIZE(right) == 1) {
9491                 direct = 1;
9492         }
9493         
9494         if (IS_BITFIELD (letype))
9495         {
9496           genPackBits (letype, result, right, direct?-1:POINTER);
9497           return;
9498         }
9499         
9500         /* If the pointer value is not in a the FSR then need to put it in */
9501         /* Must set/reset IRP bit for use with FSR. */
9502         /* Note only do this once - assuming that never need to cross a bank boundary at address 0x100. */
9503         if (!direct)
9504                 setup_fsr (result);
9505
9506         {
9507                 /* we have can just get the values */
9508                 int size = AOP_SIZE(right);
9509                 int offset = 0 ;    
9510                 
9511                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9512                 while (size--) {
9513                         char *l = aopGet(AOP(right),offset,FALSE,TRUE);
9514                         if (*l == '@' ) {
9515                                 emitpcode(POC_MOVFW,popCopyReg(&pc_indf));
9516                         } else {
9517                                 if (AOP_TYPE(right) == AOP_LIT) {
9518                                         emitpcode(POC_MOVLW,popGet(AOP(right),offset));
9519                                 } else {
9520                                         emitpcode(POC_MOVFW,popGet(AOP(right),offset));
9521                                 }
9522                                 if (direct)
9523                                         emitpcode(POC_MOVWF,popGet(AOP(result),0));
9524                                 else
9525                                         emitpcode(POC_MOVWF,popCopyReg(&pc_indf));
9526                         }
9527                         if (size && !direct)
9528                                 emitpcode(POC_INCF,popCopyReg(&pc_fsr));
9529                         offset++;
9530                 }
9531         }
9532         
9533         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9534         /* now some housekeeping stuff */
9535         if (aop) {
9536                 /* we had to allocate for this iCode */
9537                 freeAsmop(NULL,aop,ic,TRUE);
9538         } else { 
9539                 /* we did not allocate which means left
9540                 already in a pointer register, then
9541                 if size > 0 && this could be used again
9542                 we have to point it back to where it 
9543                 belongs */
9544                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9545                 if (AOP_SIZE(right) > 1 &&
9546                         !OP_SYMBOL(result)->remat &&
9547                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9548                         ic->depth )) {
9549                         int size = AOP_SIZE(right) - 1;
9550                         while (size--)
9551                                 emitpcode(POC_DECF, popCopyReg(&pc_fsr));
9552                 }
9553         }
9554         
9555         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9556         /* done */
9557
9558         freeAsmop(right,NULL,ic,TRUE);
9559         freeAsmop(result,NULL,ic,TRUE);
9560 }
9561
9562 #if 0
9563 /*-----------------------------------------------------------------*/
9564 /* genPagedPointerSet - pic14_emitcode for Paged pointer put             */
9565 /*-----------------------------------------------------------------*/
9566 static void genPagedPointerSet (operand *right,
9567                                                                 operand *result, 
9568                                                                 iCode *ic)
9569 {
9570         asmop *aop = NULL;
9571         regs *preg = NULL ;
9572         char *rname , *l;
9573         sym_link *retype;
9574         
9575         FENTRY;
9576         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9577         
9578         retype= getSpec(operandType(right));
9579         
9580         aopOp(result,ic,FALSE);
9581         
9582         /* if the value is already in a pointer register
9583         then don't need anything more */
9584         if (!AOP_INPREG(AOP(result))) {
9585                 /* otherwise get a free pointer register */
9586                 aop = newAsmop(0);
9587                 preg = getFreePtr(ic,&aop,FALSE);
9588                 pic14_emitcode("mov","%s,%s",
9589                         preg->name,
9590                         aopGet(AOP(result),0,FALSE,TRUE));
9591                 rname = preg->name ;
9592         } else
9593                 rname = aopGet(AOP(result),0,FALSE,FALSE);
9594         
9595         freeAsmop(result,NULL,ic,TRUE);
9596         aopOp (right,ic,FALSE);
9597         
9598         /* if bitfield then unpack the bits */
9599         if (IS_BITFIELD(retype)) 
9600                 genPackBits (retype,result,right,rname,PPOINTER);
9601         else {
9602                 /* we have can just get the values */
9603                 int size = AOP_SIZE(right);
9604                 int offset = 0 ;  
9605                 
9606                 while (size--) {
9607                         l = aopGet(AOP(right),offset,FALSE,TRUE);
9608                         
9609                         MOVA(l);
9610                         pic14_emitcode("movx","@%s,a",rname);
9611                         
9612                         if (size)
9613                                 pic14_emitcode("inc","%s",rname);
9614                         
9615                         offset++;
9616                 }
9617         }
9618         
9619         /* now some housekeeping stuff */
9620         if (aop) {
9621                 /* we had to allocate for this iCode */
9622                 freeAsmop(NULL,aop,ic,TRUE);
9623         } else { 
9624         /* we did not allocate which means left
9625         already in a pointer register, then
9626         if size > 0 && this could be used again
9627         we have to point it back to where it 
9628                 belongs */
9629                 if (AOP_SIZE(right) > 1 &&
9630                         !OP_SYMBOL(result)->remat &&
9631                         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9632                         ic->depth )) {
9633                         int size = AOP_SIZE(right) - 1;
9634                         while (size--)
9635                                 pic14_emitcode("dec","%s",rname);
9636                 }
9637         }
9638         
9639         /* done */
9640         freeAsmop(right,NULL,ic,TRUE);
9641         
9642         
9643 }
9644
9645 /*-----------------------------------------------------------------*/
9646 /* genFarPointerSet - set value from far space                     */
9647 /*-----------------------------------------------------------------*/
9648 static void genFarPointerSet (operand *right,
9649                                                           operand *result, iCode *ic)
9650 {
9651         int size, offset ;
9652         sym_link *retype = getSpec(operandType(right));
9653         
9654         FENTRY;
9655         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9656         aopOp(result,ic,FALSE);
9657         
9658         /* if the operand is already in dptr 
9659         then we do nothing else we move the value to dptr */
9660         if (AOP_TYPE(result) != AOP_STR) {
9661                 /* if this is remateriazable */
9662                 if (AOP_TYPE(result) == AOP_IMMD)
9663                         pic14_emitcode("mov","dptr,%s",aopGet(AOP(result),0,TRUE,FALSE));
9664                 else { /* we need to get it byte by byte */
9665                         pic14_emitcode("mov","dpl,%s",aopGet(AOP(result),0,FALSE,FALSE));
9666                         pic14_emitcode("mov","dph,%s",aopGet(AOP(result),1,FALSE,FALSE));
9667                         if (options.model == MODEL_FLAT24)
9668                         {
9669                                 pic14_emitcode("mov", "dpx,%s",aopGet(AOP(result),2,FALSE,FALSE));
9670                         }
9671                 }
9672         }
9673         /* so dptr know contains the address */
9674         freeAsmop(result,NULL,ic,TRUE);
9675         aopOp(right,ic,FALSE);
9676         
9677         /* if bit then unpack */
9678         if (IS_BITFIELD(retype)) 
9679                 genPackBits(retype,result,right,"dptr",FPOINTER);
9680         else {
9681                 size = AOP_SIZE(right);
9682                 offset = 0 ;
9683                 
9684                 while (size--) {
9685                         char *l = aopGet(AOP(right),offset++,FALSE,FALSE);
9686                         MOVA(l);
9687                         pic14_emitcode("movx","@dptr,a");
9688                         if (size)
9689                                 pic14_emitcode("inc","dptr");
9690                 }
9691         }
9692         
9693         freeAsmop(right,NULL,ic,TRUE);
9694 }
9695 #endif
9696
9697 /*-----------------------------------------------------------------*/
9698 /* genGenPointerSet - set value from generic pointer space         */
9699 /*-----------------------------------------------------------------*/
9700 static void genGenPointerSet (operand *right, operand *result, iCode *ic)
9701 {
9702         sym_link *retype = getSpec(operandType(result));
9703         
9704         FENTRY;
9705         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9706         aopOp(right,ic,FALSE);
9707         aopOp(result,ic,FALSE);
9708
9709         
9710         DEBUGpic14_AopType(__LINE__,right,NULL,result);
9711
9712         if (IS_BITFIELD(retype))
9713         {
9714           genPackBits (retype, result, right, GPOINTER);
9715           return;
9716         }
9717
9718         {
9719           /* emit call to __gptrput */
9720           char *func[] = {NULL, "__gptrput1", "__gptrput2", "__gptrput3", "__gptrput4"};
9721           int size = AOP_SIZE(right);
9722           int idx = 0;
9723
9724           assert (size == getSize(OP_SYM_ETYPE(result)));
9725           assert (size > 0 && size <= 4);
9726
9727           /* pass arguments */
9728           /* - value (MSB in Gstack_base_addr-2, growing downwards) */
9729           {
9730             int off = size;
9731             idx = 2;
9732             while (off--)
9733             {
9734               mov2w_op (right, off);
9735               emitpcode (POC_MOVWF, popRegFromIdx (Gstack_base_addr - idx++));
9736             }
9737             idx = 0;
9738           }
9739           /* - address */
9740           assert (AOP_SIZE(result) == 3);
9741           mov2w(AOP(result), 0);
9742           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr - 1));
9743           mov2w(AOP(result), 1);
9744           emitpcode(POC_MOVWF, popRegFromIdx (Gstack_base_addr));
9745           mov2w(AOP(result), 2);
9746           call_libraryfunc (func[size]);
9747         }
9748         
9749         freeAsmop(right,NULL,ic,TRUE);
9750         freeAsmop(result,NULL,ic,TRUE);
9751 }
9752
9753 /*-----------------------------------------------------------------*/
9754 /* genPointerSet - stores the value into a pointer location        */
9755 /*-----------------------------------------------------------------*/
9756 static void genPointerSet (iCode *ic)
9757 {    
9758         operand *right, *result ;
9759         sym_link *type, *etype;
9760         int p_type;
9761         
9762         FENTRY;
9763         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9764         
9765         right = IC_RIGHT(ic);
9766         result = IC_RESULT(ic) ;
9767         
9768         /* depending on the type of pointer we need to
9769         move it to the correct pointer register */
9770         type = operandType(result);
9771         etype = getSpec(type);
9772         /* if left is of type of pointer then it is simple */
9773         if (IS_PTR(type) && !IS_FUNC(type->next)) {
9774                 p_type = DCL_TYPE(type);
9775         }
9776         else {
9777                 /* we have to go by the storage class */
9778                 p_type = PTR_TYPE(SPEC_OCLS(etype));
9779                 
9780                 /*  if (SPEC_OCLS(etype)->codesp ) { */
9781                 /*      p_type = CPOINTER ;  */
9782                 /*  } */
9783                 /*  else */
9784                 /*      if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9785                 /*    p_type = FPOINTER ; */
9786                 /*      else */
9787                 /*    if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9788                 /*        p_type = PPOINTER ; */
9789                 /*    else */
9790                 /*        if (SPEC_OCLS(etype) == idata ) */
9791                 /*      p_type = IPOINTER ; */
9792                 /*        else */
9793                 /*      p_type = POINTER ; */
9794         }
9795         
9796         /* now that we have the pointer type we assign
9797         the pointer values */
9798         switch (p_type) {
9799                 
9800         case POINTER:
9801         case FPOINTER:
9802         //case IPOINTER:
9803                 genNearPointerSet (right,result,ic);
9804                 break;
9805 /*
9806         case PPOINTER:
9807                 genPagedPointerSet (right,result,ic);
9808                 break;
9809                 
9810         case FPOINTER:
9811                 genFarPointerSet (right,result,ic);
9812                 break;
9813 */
9814         case GPOINTER:
9815                 genGenPointerSet (right,result,ic);
9816                 break;
9817                 
9818         default:
9819                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9820                         "genPointerSet: illegal pointer type");
9821         }
9822 }
9823
9824 /*-----------------------------------------------------------------*/
9825 /* genIfx - generate code for Ifx statement                        */
9826 /*-----------------------------------------------------------------*/
9827 static void genIfx (iCode *ic, iCode *popIc)
9828 {
9829         operand *cond = IC_COND(ic);
9830         int isbit =0;
9831         
9832         FENTRY;
9833         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9834         
9835         aopOp(cond,ic,FALSE);
9836         
9837         /* get the value into acc */
9838         if (AOP_TYPE(cond) != AOP_CRY)
9839                 pic14_toBoolean(cond);
9840         else
9841                 isbit = 1;
9842         
9843         /* if there was something to be popped then do it */
9844         if (popIc)
9845                 genIpop(popIc);
9846         
9847         if (isbit)
9848         {
9849                 /* This assumes that CARRY is set iff cond is true */
9850                 if (IC_TRUE(ic))
9851                 {
9852                         assert (!IC_FALSE(ic));
9853                         emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
9854                         //emitSKPNC;
9855                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9856                 } else {
9857                         assert (IC_FALSE(ic));
9858                         emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
9859                         //emitSKPC;
9860                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9861                 }
9862                 if (0)
9863                 {
9864                         static int hasWarned = 0;
9865                         if (!hasWarned)
9866                         {
9867                                 fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
9868                                 hasWarned = 1;
9869                         }
9870                 }
9871         }
9872         else
9873         {
9874                 /* now Z is set iff !cond */
9875                 if (IC_TRUE(ic))
9876                 {
9877                         assert (!IC_FALSE(ic));
9878                         emitSKPZ;
9879                         emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
9880                 } else {
9881                         emitSKPNZ;
9882                         emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
9883                 }
9884         }
9885         
9886         ic->generated = 1;
9887         
9888         /* the result is now in the accumulator */
9889         freeAsmop(cond,NULL,ic,TRUE);
9890 }
9891
9892 /*-----------------------------------------------------------------*/
9893 /* genAddrOf - generates code for address of                       */
9894 /*-----------------------------------------------------------------*/
9895 static void genAddrOf (iCode *ic)
9896 {
9897         operand *right, *result, *left;
9898         int size, offset ;
9899         
9900         FENTRY;
9901         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9902         
9903         
9904         //aopOp(IC_RESULT(ic),ic,FALSE);
9905         
9906         aopOp((left=IC_LEFT(ic)),ic,FALSE);
9907         aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9908         aopOp((result=IC_RESULT(ic)),ic,TRUE);
9909         
9910         DEBUGpic14_AopType(__LINE__,left,right,result);
9911         assert (IS_SYMOP (left));
9912         
9913         /* sanity check: generic pointers to code space are not yet supported,
9914          * pionters to codespace must not be assigned addresses of __data values. */
9915  #if 0
9916         fprintf (stderr, "result: %s, left: %s\n", OP_SYMBOL(result)->name, OP_SYMBOL(left)->name);
9917         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)));
9918         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)));
9919         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)));
9920         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)));
9921 #endif
9922
9923         if (IS_CODEPTR(OP_SYM_TYPE(result)) && !IN_CODESPACE(SPEC_OCLS(getSpec (OP_SYM_TYPE(left))))) {
9924           fprintf (stderr, "trying to assign __code pointer (%s) an address in __data space (&%s) -- expect trouble\n",
9925                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9926                 OP_SYMBOL(left)->name);
9927         } else if (!IS_CODEPTR (OP_SYM_TYPE(result)) && IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))))) {
9928           fprintf (stderr, "trying to assign __data pointer (%s) an address in __code space (&%s) -- expect trouble\n",
9929                 IS_SYMOP(result) ? OP_SYMBOL(result)->name : "unknown",
9930                 OP_SYMBOL(left)->name);
9931         }
9932         
9933         size = AOP_SIZE(IC_RESULT(ic));
9934         if (IS_GENPTR(OP_SYM_TYPE(result))) {
9935                 /* strip tag */
9936                 if (size > GPTRSIZE-1) size = GPTRSIZE-1;
9937         }
9938         offset = 0;
9939         
9940         while (size--) {
9941                 /* fixing bug #863624, reported from (errolv) */
9942                 emitpcode(POC_MOVLW, popGetImmd(OP_SYMBOL(left)->rname, offset, 0, IS_FUNC(OP_SYM_TYPE(left))));
9943                 emitpcode(POC_MOVWF, popGet(AOP(result), offset));
9944                 
9945 #if 0
9946                 emitpcode(POC_MOVLW, popGet(AOP(left),offset));
9947                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
9948 #endif
9949                 offset++;
9950         }
9951
9952         if (IS_GENPTR(OP_SYM_TYPE(result)))
9953         {
9954                 /* provide correct tag */
9955                 int isCode = IN_CODESPACE(SPEC_OCLS(getSpec(OP_SYM_TYPE(left))));
9956                 emitpcode (POC_MOVLW, popGetLit (isCode ? GPTRTAG_CODE : GPTRTAG_DATA));
9957                 movwf (AOP(result), 2);
9958         }
9959         
9960         freeAsmop(left,NULL,ic,FALSE);
9961         freeAsmop(result,NULL,ic,TRUE);
9962         
9963 }
9964
9965 #if 0
9966 /*-----------------------------------------------------------------*/
9967 /* genFarFarAssign - assignment when both are in far space         */
9968 /*-----------------------------------------------------------------*/
9969 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9970 {
9971         int size = AOP_SIZE(right);
9972         int offset = 0;
9973         char *l ;
9974         /* first push the right side on to the stack */
9975         while (size--) {
9976                 l = aopGet(AOP(right),offset++,FALSE,FALSE);
9977                 MOVA(l);
9978                 pic14_emitcode ("push","acc");
9979         }
9980         
9981         freeAsmop(right,NULL,ic,FALSE);
9982         /* now assign DPTR to result */
9983         aopOp(result,ic,FALSE);
9984         size = AOP_SIZE(result);
9985         while (size--) {
9986                 pic14_emitcode ("pop","acc");
9987                 aopPut(AOP(result),"a",--offset);
9988         }
9989         freeAsmop(result,NULL,ic,FALSE);
9990         
9991 }
9992 #endif
9993
9994 /*-----------------------------------------------------------------*/
9995 /* genAssign - generate code for assignment                        */
9996 /*-----------------------------------------------------------------*/
9997 static void genAssign (iCode *ic)
9998 {
9999         operand *result, *right;
10000         int size, offset,know_W;
10001         unsigned long lit = 0L;
10002         
10003         result = IC_RESULT(ic);
10004         right  = IC_RIGHT(ic) ;
10005         
10006         FENTRY;
10007         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10008         
10009         /* if they are the same */
10010         if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10011                 return ;
10012         
10013         aopOp(right,ic,FALSE);
10014         aopOp(result,ic,TRUE);
10015         
10016         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10017         
10018         /* if they are the same registers */
10019         if (pic14_sameRegs(AOP(right),AOP(result)))
10020                 goto release;
10021
10022         /* special case: assign from __code */
10023         if (!IS_ITEMP(right)                            /* --> iTemps never reside in __code */
10024                 && IS_SYMOP (right)                     /* --> must be an immediate (otherwise we would be in genConstPointerGet) */
10025                 && !IS_FUNC(OP_SYM_TYPE(right))         /* --> we would want its address instead of the first instruction */
10026                 && !IS_CODEPTR(OP_SYM_TYPE(right))      /* --> get symbols address instread */
10027                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(right)))))
10028         {
10029           emitpComment ("genAssign from CODESPACE");
10030           genConstPointerGet (right, result, ic);
10031           goto release;
10032         }
10033         
10034         /* just for symmetry reasons... */
10035         if (!IS_ITEMP(result)
10036                 && IS_SYMOP (result)
10037                 && IN_CODESPACE (SPEC_OCLS (getSpec (OP_SYM_TYPE(result)))))
10038         {
10039           assert ( !"cannot write to CODESPACE" );
10040         }
10041
10042         /* if the result is a bit */
10043         if (AOP_TYPE(result) == AOP_CRY) {
10044                 
10045         /* if the right size is a literal then
10046                 we know what the value is */
10047                 if (AOP_TYPE(right) == AOP_LIT) {
10048                         
10049                         emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10050                                 popGet(AOP(result),0));
10051                         
10052                         if (((int) operandLitValue(right))) 
10053                                 pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10054                                 AOP(result)->aopu.aop_dir,
10055                                 AOP(result)->aopu.aop_dir);
10056                         else
10057                                 pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10058                                 AOP(result)->aopu.aop_dir,
10059                                 AOP(result)->aopu.aop_dir);
10060                         goto release;
10061                 }
10062                 
10063                 /* the right is also a bit variable */
10064                 if (AOP_TYPE(right) == AOP_CRY) {
10065                         emitpcode(POC_BCF,    popGet(AOP(result),0));
10066                         emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10067                         emitpcode(POC_BSF,    popGet(AOP(result),0));
10068                         
10069                         pic14_emitcode("bcf","(%s >> 3),(%s & 7)",
10070                                 AOP(result)->aopu.aop_dir,
10071                                 AOP(result)->aopu.aop_dir);
10072                         pic14_emitcode("btfsc","(%s >> 3),(%s & 7)",
10073                                 AOP(right)->aopu.aop_dir,
10074                                 AOP(right)->aopu.aop_dir);
10075                         pic14_emitcode("bsf","(%s >> 3),(%s & 7)",
10076                                 AOP(result)->aopu.aop_dir,
10077                                 AOP(result)->aopu.aop_dir);
10078                         goto release ;
10079                 }
10080                 
10081                 /* we need to or */
10082                 emitpcode(POC_BCF,    popGet(AOP(result),0));
10083                 pic14_toBoolean(right);
10084                 emitSKPZ;
10085                 emitpcode(POC_BSF,    popGet(AOP(result),0));
10086                 //aopPut(AOP(result),"a",0);
10087                 goto release ;
10088         }
10089         
10090         /* bit variables done */
10091         /* general case */
10092         size = AOP_SIZE(result);
10093         offset = 0 ;
10094         if(AOP_TYPE(right) == AOP_LIT)
10095                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10096         
10097         if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10098                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10099                 if(aopIdx(AOP(result),0) == 4) {
10100                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10101                         emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10102                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10103                         goto release;
10104                 } else
10105                         DEBUGpic14_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10106         }
10107         
10108         know_W=-1;
10109         while (size--) {
10110                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10111                 if(AOP_TYPE(right) == AOP_LIT) {
10112                         if(lit&0xff) {
10113                                 if(know_W != (int)(lit&0xff))
10114                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
10115                                 know_W = lit&0xff;
10116                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10117                         } else
10118                                 emitpcode(POC_CLRF, popGet(AOP(result),offset));
10119                         
10120                         lit >>= 8;
10121                         
10122                 } else if (AOP_TYPE(right) == AOP_CRY) {
10123                         emitpcode(POC_CLRF, popGet(AOP(result),offset));
10124                         if(offset == 0) {
10125                                 emitpcode(POC_BTFSS, popGet(AOP(right),0));
10126                                 emitpcode(POC_INCF, popGet(AOP(result),0));
10127                         }
10128                 } else {
10129                         mov2w_op (right, offset);
10130                         emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10131                 }
10132                 
10133                 offset++;
10134         }
10135         
10136         
10137 release:
10138         freeAsmop (right,NULL,ic,FALSE);
10139         freeAsmop (result,NULL,ic,TRUE);
10140 }   
10141
10142 /*-----------------------------------------------------------------*/
10143 /* genJumpTab - genrates code for jump table                       */
10144 /*-----------------------------------------------------------------*/
10145 static void genJumpTab (iCode *ic)
10146 {
10147         symbol *jtab;
10148         char *l;
10149         
10150         FENTRY;
10151         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10152         
10153         aopOp(IC_JTCOND(ic),ic,FALSE);
10154         /* get the condition into accumulator */
10155         l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10156         MOVA(l);
10157         /* multiply by three */
10158         pic14_emitcode("add","a,acc");
10159         pic14_emitcode("add","a,%s",aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10160         
10161         jtab = newiTempLabel(NULL);
10162         pic14_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10163         pic14_emitcode("jmp","@a+dptr");
10164         pic14_emitcode("","%05d_DS_:",jtab->key+100);
10165         
10166         emitpcode(POC_MOVLW, popGetHighLabel(jtab->key));
10167         emitpcode(POC_MOVWF, popCopyReg(&pc_pclath));
10168         emitpcode(POC_MOVLW, popGetLabel(jtab->key));
10169         emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0));
10170         emitSKPNC;
10171         emitpcode(POC_INCF, popCopyReg(&pc_pclath));
10172         emitpcode(POC_MOVWF, popCopyReg(&pc_pcl));
10173         emitpLabel(jtab->key);
10174         
10175         freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10176         
10177         /* now generate the jump labels */
10178         for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10179         jtab = setNextItem(IC_JTLABELS(ic))) {
10180                 pic14_emitcode("ljmp","%05d_DS_",jtab->key+100);
10181                 emitpcode(POC_GOTO,popGetLabel(jtab->key));
10182                 
10183         }
10184         
10185 }
10186
10187 /*-----------------------------------------------------------------*/
10188 /* genMixedOperation - gen code for operators between mixed types  */
10189 /*-----------------------------------------------------------------*/
10190 /*
10191 TSD - Written for the PIC port - but this unfortunately is buggy.
10192 This routine is good in that it is able to efficiently promote 
10193 types to different (larger) sizes. Unfortunately, the temporary
10194 variables that are optimized out by this routine are sometimes
10195 used in other places. So until I know how to really parse the 
10196 iCode tree, I'm going to not be using this routine :(.
10197 */
10198 static int genMixedOperation (iCode *ic)
10199 {
10200         FENTRY;
10201 #if 0
10202         operand *result = IC_RESULT(ic);
10203         sym_link *ctype = operandType(IC_LEFT(ic));
10204         operand *right = IC_RIGHT(ic);
10205         int ret = 0;
10206         int big,small;
10207         int offset;
10208         
10209         iCode *nextic;
10210         operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10211         
10212         pic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10213         
10214         nextic = ic->next;
10215         if(!nextic)
10216                 return 0;
10217         
10218         nextright = IC_RIGHT(nextic);
10219         nextleft  = IC_LEFT(nextic);
10220         nextresult = IC_RESULT(nextic);
10221         
10222         aopOp(right,ic,FALSE);
10223         aopOp(result,ic,FALSE);
10224         aopOp(nextright,  nextic, FALSE);
10225         aopOp(nextleft,   nextic, FALSE);
10226         aopOp(nextresult, nextic, FALSE);
10227         
10228         if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10229                 
10230                 operand *t = right;
10231                 right = nextright;
10232                 nextright = t; 
10233                 
10234                 pic14_emitcode(";remove right +","");
10235                 
10236         } else   if (pic14_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10237         /*
10238         operand *t = right;
10239         right = nextleft;
10240         nextleft = t; 
10241                 */
10242                 pic14_emitcode(";remove left +","");
10243         } else
10244                 return 0;
10245         
10246         big = AOP_SIZE(nextleft);
10247         small = AOP_SIZE(nextright);
10248         
10249         switch(nextic->op) {
10250                 
10251         case '+':
10252                 pic14_emitcode(";optimize a +","");
10253                 /* if unsigned or not an integral type */
10254                 if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10255                         pic14_emitcode(";add a bit to something","");
10256                 } else {
10257                         
10258                         pic14_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10259                         
10260                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10261                                 pic14_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10262                                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10263                         } else
10264                                 pic14_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10265                         
10266                         offset = 0;
10267                         while(--big) {
10268                                 
10269                                 offset++;
10270                                 
10271                                 if(--small) {
10272                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10273                                                 pic14_emitcode("movf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10274                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10275                                         }
10276                                         
10277                                         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10278                                         emitSKPNC;
10279                                         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
10280                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10281                                                 AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10282                                         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10283                                         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10284                                         
10285                                 } else {
10286                                         pic14_emitcode("rlf","known_zero,w");
10287                                         
10288                                         /*
10289                                         if right is signed
10290                                         btfsc  right,7
10291                                         addlw ff
10292                                         */
10293                                         if (!pic14_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10294                                                 pic14_emitcode("addwf","%s,w",aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10295                                                 pic14_emitcode("movwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10296                                         } else {
10297                                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10298                                         }
10299                                 }
10300                         }
10301                         ret = 1;
10302                 }
10303         }
10304         ret = 1;
10305         
10306 release:
10307         freeAsmop(right,NULL,ic,TRUE);
10308         freeAsmop(result,NULL,ic,TRUE);
10309         freeAsmop(nextright,NULL,ic,TRUE);
10310         freeAsmop(nextleft,NULL,ic,TRUE);
10311         if(ret)
10312                 nextic->generated = 1;
10313         
10314         return ret;
10315 #else
10316         return 0;
10317 #endif
10318 }
10319 /*-----------------------------------------------------------------*/
10320 /* genCast - gen code for casting                                  */
10321 /*-----------------------------------------------------------------*/
10322 static void genCast (iCode *ic)
10323 {
10324         operand *result = IC_RESULT(ic);
10325         sym_link *restype = operandType(result);
10326         sym_link *rtype = operandType(IC_RIGHT(ic));
10327         operand *right = IC_RIGHT(ic);
10328         int size, offset ;
10329         
10330         FENTRY;
10331         DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10332         /* if they are equivalent then do nothing */
10333         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10334                 return ;
10335         
10336         aopOp(right,ic,FALSE) ;
10337         aopOp(result,ic,FALSE);
10338         
10339         DEBUGpic14_AopType(__LINE__,NULL,right,result);
10340         
10341         /* if the result is a bit */
10342         if (AOP_TYPE(result) == AOP_CRY) {
10343                 assert(!"assigning to bit variables is not supported");
10344         }
10345         
10346         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10347                 int offset = 1;
10348                 size = AOP_SIZE(result);
10349                 
10350                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10351                 
10352                 emitpcode(POC_CLRF,   popGet(AOP(result),0));
10353                 emitpcode(POC_BTFSC,  popGet(AOP(right),0));
10354                 emitpcode(POC_INCF,   popGet(AOP(result),0));
10355                 
10356                 while (size--)
10357                         emitpcode(POC_CLRF,   popGet(AOP(result),offset++));
10358                 
10359                 goto release;
10360         }
10361         
10362         if (IS_PTR(restype))
10363         {
10364           operand *result = IC_RESULT(ic);
10365           //operand *left = IC_LEFT(ic);
10366           operand *right = IC_RIGHT(ic);
10367           int tag = 0xff;
10368           
10369           /* copy common part */
10370           int max, size = AOP_SIZE(result);
10371           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
10372           DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10373
10374           /* warn if we discard generic opinter tag */
10375           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
10376           {
10377             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
10378           } // if
10379
10380           max = size;
10381           while (size--)
10382           {
10383             mov2w_op (right, size);
10384             movwf (AOP(result), size);
10385           } // while
10386
10387           /* upcast into generic pointer type? */
10388           if (IS_GENPTR(restype)
10389                 && (size < AOP_SIZE(result))
10390                 && (!IS_GENPTR(rtype) || AOP_SIZE(right) < GPTRSIZE))
10391           {
10392             //fprintf (stderr, "%s:%u: must determine pointer type\n", __FUNCTION__, __LINE__);
10393             if (IS_PTR(rtype))
10394             {
10395               switch (DCL_TYPE(rtype))
10396               {
10397               case POINTER:     /* __data */
10398               case FPOINTER:    /* __data */
10399                 assert (AOP_SIZE(right) == 2);
10400                 tag = GPTRTAG_DATA;
10401                 break;
10402
10403               case CPOINTER:    /* __code */
10404                 assert (AOP_SIZE(right) == 2);
10405                 tag = GPTRTAG_CODE;
10406                 break;
10407                 
10408               case GPOINTER:    /* unknown destination, __data or __code */
10409                 /* assume __data space (address of immediate) */
10410                 assert (AOP_TYPE(right) == AOP_PCODE && AOP(right)->aopu.pcop->type == PO_IMMEDIATE);
10411                 if (AOP(right)->code)
10412                   tag = GPTRTAG_CODE;
10413                 else
10414                   tag = GPTRTAG_DATA;
10415                 break;
10416                 
10417               default:
10418                 assert (!"unhandled pointer type");
10419               } // switch
10420             } else {
10421               /* convert other values into pointers to __data space */
10422               tag = GPTRTAG_DATA;
10423             }
10424
10425             assert (AOP_SIZE(result) == 3);
10426             if (tag == 0) {
10427               emitpcode(POC_CLRF, popGet(AOP(result), 2));
10428             } else {
10429               emitpcode(POC_MOVLW, popGetLit(tag));
10430               movwf(AOP(result), 2);
10431             }
10432           } else {
10433             addSign(result, max, 0);
10434           } // if
10435           goto release;
10436         }
10437         
10438         /* if they are the same size : or less */
10439         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10440                 
10441                 /* if they are in the same place */
10442                 if (pic14_sameRegs(AOP(right),AOP(result)))
10443                         goto release;
10444                 
10445                 DEBUGpic14_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10446                 if (IS_PTR_CONST(rtype))
10447                         DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
10448                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10449                         DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
10450                 
10451                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10452                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),0,0));
10453                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
10454                         emitpcode(POC_MOVLW, popGetAddr(AOP(right),1,0));
10455                         emitpcode(POC_MOVWF, popGet(AOP(result),1));
10456                         if(AOP_SIZE(result) <2)
10457                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10458                         
10459                 } else {
10460                         
10461                         /* if they in different places then copy */
10462                         size = AOP_SIZE(result);
10463                         offset = 0 ;
10464                         while (size--) {
10465                                 emitpcode(POC_MOVFW, popGet(AOP(right),offset));
10466                                 emitpcode(POC_MOVWF, popGet(AOP(result),offset));
10467                                 
10468                                 //aopPut(AOP(result),
10469                                 // aopGet(AOP(right),offset,FALSE,FALSE),
10470                                 // offset);
10471                                 
10472                                 offset++;
10473                         }
10474                 }
10475                 goto release;
10476         }
10477         
10478         /* so we now know that the size of destination is greater
10479         than the size of the source.
10480         Now, if the next iCode is an operator then we might be
10481         able to optimize the operation without performing a cast.
10482         */
10483         if(0 && genMixedOperation(ic)) {
10484                 /* XXX: cannot optimize: must copy regs! */
10485                 goto release;
10486         }
10487         
10488         /* we move to result for the size of source */
10489         size = AOP_SIZE(right);
10490         offset = 0 ;
10491         while (size--) {
10492                 emitpcode(POC_MOVFW,   popGet(AOP(right),offset));
10493                 emitpcode(POC_MOVWF,   popGet(AOP(result),offset));
10494                 offset++;
10495         }
10496
10497         addSign (result, AOP_SIZE(right), !SPEC_USIGN(rtype));
10498
10499 release:
10500         freeAsmop(right,NULL,ic,TRUE);
10501         freeAsmop(result,NULL,ic,TRUE);
10502         
10503 }
10504
10505 /*-----------------------------------------------------------------*/
10506 /* genDjnz - generate decrement & jump if not zero instrucion      */
10507 /*-----------------------------------------------------------------*/
10508 static int genDjnz (iCode *ic, iCode *ifx)
10509 {
10510         symbol *lbl, *lbl1;
10511         FENTRY;
10512         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10513         
10514         if (!ifx)
10515                 return 0;
10516         
10517                 /* if the if condition has a false label
10518         then we cannot save */
10519         if (IC_FALSE(ifx))
10520                 return 0;
10521         
10522                 /* if the minus is not of the form 
10523         a = a - 1 */
10524         if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10525                 !IS_OP_LITERAL(IC_RIGHT(ic)))
10526                 return 0;
10527         
10528         if (operandLitValue(IC_RIGHT(ic)) != 1)
10529                 return 0;
10530         
10531                 /* if the size of this greater than one then no
10532         saving */
10533         if (getSize(operandType(IC_RESULT(ic))) > 1)
10534                 return 0;
10535         
10536         /* otherwise we can save BIG */
10537         lbl = newiTempLabel(NULL);
10538         lbl1= newiTempLabel(NULL);
10539         
10540         aopOp(IC_RESULT(ic),ic,FALSE);
10541         
10542         if (IS_AOP_PREG(IC_RESULT(ic))) {
10543                 pic14_emitcode("dec","%s",
10544                         aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10545                 pic14_emitcode("mov","a,%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10546                 pic14_emitcode("jnz","%05d_DS_",lbl->key+100);
10547         } else {  
10548                 
10549                 
10550                 emitpcode(POC_DECFSZ,popGet(AOP(IC_RESULT(ic)),0));
10551                 emitpcode(POC_GOTO,popGetLabel(IC_TRUE(ifx)->key));
10552                 
10553                 pic14_emitcode("decfsz","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10554                 pic14_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10555                 
10556         }
10557         /*     pic14_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10558         /*     pic14_emitcode ("","%05d_DS_:",lbl->key+100); */
10559         /*     pic14_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10560         /*     pic14_emitcode ("","%05d_DS_:",lbl1->key+100); */
10561         
10562         
10563         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10564         ifx->generated = 1;
10565         return 1;
10566 }
10567
10568 /*-----------------------------------------------------------------*/
10569 /* genReceive - generate code for a receive iCode                  */
10570 /*-----------------------------------------------------------------*/
10571 static void genReceive (iCode *ic)
10572 {
10573         FENTRY;
10574         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10575         
10576         if (isOperandInFarSpace(IC_RESULT(ic)) &&
10577                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10578                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10579                 
10580                 int size = getSize(operandType(IC_RESULT(ic)));
10581                 int offset =  fReturnSizePic - size;
10582                 while (size--) {
10583                         pic14_emitcode ("push","%s", (strcmp(fReturn[fReturnSizePic - offset - 1],"a") ?
10584                                 fReturn[fReturnSizePic - offset - 1] : "acc"));
10585                         offset++;
10586                 }
10587                 aopOp(IC_RESULT(ic),ic,FALSE);
10588                 size = AOP_SIZE(IC_RESULT(ic));
10589                 offset = 0;
10590                 while (size--) {
10591                         pic14_emitcode ("pop","acc");
10592                         aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10593                 }
10594                 
10595         } else {
10596                 _G.accInUse++;
10597                 aopOp(IC_RESULT(ic),ic,FALSE);
10598                 _G.accInUse--;
10599                 assignResultValue(IC_RESULT(ic));
10600         }
10601         
10602         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10603 }
10604
10605 /*-----------------------------------------------------------------*/
10606 /* genDummyRead - generate code for dummy read of volatiles        */
10607 /*-----------------------------------------------------------------*/
10608 static void
10609 genDummyRead (iCode * ic)
10610 {
10611         FENTRY;
10612         pic14_emitcode ("; genDummyRead","");
10613         pic14_emitcode ("; not implemented","");
10614         
10615         ic = ic;
10616 }
10617
10618 /*-----------------------------------------------------------------*/
10619 /* genpic14Code - generate code for pic14 based controllers        */
10620 /*-----------------------------------------------------------------*/
10621 /*
10622 * At this point, ralloc.c has gone through the iCode and attempted
10623 * to optimize in a way suitable for a PIC. Now we've got to generate
10624 * PIC instructions that correspond to the iCode.
10625 *
10626 * Once the instructions are generated, we'll pass through both the
10627 * peep hole optimizer and the pCode optimizer.
10628 *-----------------------------------------------------------------*/
10629
10630 void genpic14Code (iCode *lic)
10631 {
10632         iCode *ic;
10633         int cln = 0;
10634         const char *cline;
10635         
10636         FENTRY;
10637         lineHead = lineCurr = NULL;
10638         
10639         pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
10640         addpBlock(pb);
10641         
10642         /* if debug information required */
10643         if (options.debug && currFunc) { 
10644                 if (currFunc) {
10645                         debugFile->writeFunction (currFunc, lic);
10646                 }
10647         }
10648         
10649         
10650         for (ic = lic ; ic ; ic = ic->next ) {
10651                 
10652                 //DEBUGpic14_emitcode(";ic","");
10653                 //fprintf (stderr, "in ic loop\n");
10654                 //pic14_emitcode ("", ";\t%s:%d: %s", ic->filename,
10655                 //ic->lineno, printCLine(ic->filename, ic->lineno));
10656                 
10657                 if (!options.noCcodeInAsm && (cln != ic->lineno)) {
10658                   cln = ic->lineno;
10659                   //fprintf (stderr, "%s\n", printCLine (ic->filename, ic->lineno));
10660                   cline = printCLine (ic->filename, ic->lineno);
10661                   if (!cline || strlen (cline) == 0) cline = printCLine (ic->filename, ic->lineno);
10662                   addpCode2pBlock (pb, newpCodeCSource (ic->lineno, ic->filename, cline));
10663                   //emitpComment ("[C-SRC] %s:%d: %s", ic->filename, cln, cline);
10664                 }
10665                 
10666                 if (options.iCodeInAsm) {
10667                   emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
10668                 }
10669                 /* if the result is marked as
10670                 spilt and rematerializable or code for
10671                 this has already been generated then
10672                 do nothing */
10673                 if (resultRemat(ic) || ic->generated ) 
10674                         continue ;
10675                 
10676                 /* depending on the operation */
10677                 switch (ic->op) {
10678                 case '!' :
10679                         genNot(ic);
10680                         break;
10681                         
10682                 case '~' :
10683                         genCpl(ic);
10684                         break;
10685                         
10686                 case UNARYMINUS:
10687                         genUminus (ic);
10688                         break;
10689                         
10690                 case IPUSH:
10691                         genIpush (ic);
10692                         break;
10693                         
10694                 case IPOP:
10695                         /* IPOP happens only when trying to restore a 
10696                         spilt live range, if there is an ifx statement
10697                         following this pop then the if statement might
10698                         be using some of the registers being popped which
10699                         would destory the contents of the register so
10700                         we need to check for this condition and handle it */
10701                         if (ic->next            && 
10702                                 ic->next->op == IFX &&
10703                                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10704                                 genIfx (ic->next,ic);
10705                         else
10706                                 genIpop (ic);
10707                         break; 
10708                         
10709                 case CALL:
10710                         genCall (ic);
10711                         break;
10712                         
10713                 case PCALL:
10714                         genPcall (ic);
10715                         break;
10716                         
10717                 case FUNCTION:
10718                         genFunction (ic);
10719                         break;
10720                         
10721                 case ENDFUNCTION:
10722                         genEndFunction (ic);
10723                         break;
10724                         
10725                 case RETURN:
10726                         genRet (ic);
10727                         break;
10728                         
10729                 case LABEL:
10730                         genLabel (ic);
10731                         break;
10732                         
10733                 case GOTO:
10734                         genGoto (ic);
10735                         break;
10736                         
10737                 case '+' :
10738                         genPlus (ic) ;
10739                         break;
10740                         
10741                 case '-' :
10742                         if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10743                                 genMinus (ic);
10744                         break;
10745                         
10746                 case '*' :
10747                         genMult (ic);
10748                         break;
10749                         
10750                 case '/' :
10751                         genDiv (ic) ;
10752                         break;
10753                         
10754                 case '%' :
10755                         genMod (ic);
10756                         break;
10757                         
10758                 case '>' :
10759                         genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));         
10760                         break;
10761                         
10762                 case '<' :
10763                         genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10764                         break;
10765                         
10766                 case LE_OP:
10767                 case GE_OP:
10768                 case NE_OP:
10769                         
10770                         /* note these two are xlated by algebraic equivalence
10771                         during parsing SDCC.y */
10772                         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10773                                 "got '>=' or '<=' shouldn't have come here");
10774                         break;  
10775                         
10776                 case EQ_OP:
10777                         genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10778                         break;      
10779                         
10780                 case AND_OP:
10781                         genAndOp (ic);
10782                         break;
10783                         
10784                 case OR_OP:
10785                         genOrOp (ic);
10786                         break;
10787                         
10788                 case '^' :
10789                         genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10790                         break;
10791                         
10792                 case '|' :
10793                         genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10794                         break;
10795                         
10796                 case BITWISEAND:
10797                         genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10798                         break;
10799                         
10800                 case INLINEASM:
10801                         genInline (ic);
10802                         break;
10803                         
10804                 case RRC:
10805                         genRRC (ic);
10806                         break;
10807                         
10808                 case RLC:
10809                         genRLC (ic);
10810                         break;
10811                         
10812                 case GETHBIT:
10813                         genGetHbit (ic);
10814                         break;
10815                         
10816                 case LEFT_OP:
10817                         genLeftShift (ic);
10818                         break;
10819                         
10820                 case RIGHT_OP:
10821                         genRightShift (ic);
10822                         break;
10823                         
10824                 case GET_VALUE_AT_ADDRESS:
10825                         genPointerGet(ic);
10826                         break;
10827                         
10828                 case '=' :
10829                         if (POINTER_SET(ic))
10830                                 genPointerSet(ic);
10831                         else
10832                                 genAssign(ic);
10833                         break;
10834                         
10835                 case IFX:
10836                         genIfx (ic,NULL);
10837                         break;
10838                         
10839                 case ADDRESS_OF:
10840                         genAddrOf (ic);
10841                         break;
10842                         
10843                 case JUMPTABLE:
10844                         genJumpTab (ic);
10845                         break;
10846                         
10847                 case CAST:
10848                         genCast (ic);
10849                         break;
10850                         
10851                 case RECEIVE:
10852                         genReceive(ic);
10853                         break;
10854                         
10855                 case SEND:
10856                         addSet(&_G.sendSet,ic);
10857                         break;
10858                         
10859                 case DUMMY_READ_VOLATILE:
10860                         genDummyRead (ic);
10861                         break;
10862                         
10863                 default :
10864                         fprintf(stderr, "UNHANDLED iCode: "); piCode(ic, stderr);
10865                         ic = ic;
10866                         break;
10867                 }
10868         }
10869
10870         
10871         /* now we are ready to call the
10872         peep hole optimizer */
10873         if (!options.nopeep) {
10874                 peepHole (&lineHead);
10875         }
10876         /* now do the actual printing */
10877         printLine (lineHead,codeOutFile);
10878         
10879 #ifdef PCODE_DEBUG
10880         DFPRINTF((stderr,"printing pBlock\n\n"));
10881         printpBlock(stdout,pb);
10882 #endif
10883         
10884         return;
10885 }
10886
10887 /* This is not safe, as a AOP_PCODE/PO_IMMEDIATE might be used both as literal
10888  * (meaning: representing its own address) or not (referencing its contents).
10889  * This can only be decided based on the operand's type. */
10890 int
10891 aop_isLitLike (asmop *aop)
10892 {
10893   assert (aop);
10894   if (aop->type == AOP_LIT) return 1;
10895 if (aop->type == AOP_IMMD) return 1;
10896   if ((aop->type == AOP_PCODE) &&
10897                 ((aop->aopu.pcop->type == PO_LITERAL)))
10898   {
10899     /* this should be treated like a literal/immediate (use MOVLW/ADDLW/SUBLW
10900      * instead of MOVFW/ADDFW/SUBFW, use popGetAddr instead of popGet) */
10901     return 1;
10902   }
10903   return 0;
10904 }
10905
10906 int
10907 op_isLitLike (operand *op)
10908 {
10909   assert (op);
10910   if (aop_isLitLike (AOP(op))) return 1;
10911   if (IS_FUNC(OP_SYM_TYPE(op))) return 1;
10912   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
10913   return 0;
10914 }